1 /**
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 
17 #include "VtsComposerClient.h"
18 #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 
25 using namespace std::chrono_literals;
26 
27 namespace aidl::android::hardware::graphics::composer3::vts {
28 
VtsComposerClient(const std::string & name)29 VtsComposerClient::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     const auto& [status, capabilities] = getCapabilities();
38     EXPECT_TRUE(status.isOk());
39     if (std::any_of(capabilities.begin(), capabilities.end(), [&](const Capability& cap) {
40             return cap == Capability::LAYER_LIFECYCLE_BATCH_COMMAND;
41         })) {
42         mSupportsBatchedCreateLayer = true;
43     }
44 }
45 
createClient()46 ScopedAStatus VtsComposerClient::createClient() {
47     if (mComposer == nullptr) {
48         ALOGE("IComposer not initialized");
49         return ScopedAStatus::fromServiceSpecificError(IComposerClient::INVALID_CONFIGURATION);
50     }
51     auto status = mComposer->createClient(&mComposerClient);
52     if (!status.isOk() || mComposerClient == nullptr) {
53         ALOGE("Failed to create client for IComposerClient with %s",
54               status.getDescription().c_str());
55         return status;
56     }
57     mComposerCallback = SharedRefBase::make<GraphicsComposerCallback>();
58     if (mComposerCallback == nullptr) {
59         ALOGE("Unable to create ComposerCallback");
60         return ScopedAStatus::fromServiceSpecificError(IComposerClient::INVALID_CONFIGURATION);
61     }
62     return mComposerClient->registerCallback(mComposerCallback);
63 }
64 
tearDown(ComposerClientWriter * writer)65 bool VtsComposerClient::tearDown(ComposerClientWriter* writer) {
66     return verifyComposerCallbackParams() && destroyAllLayers(writer);
67 }
68 
getInterfaceVersion() const69 std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() const {
70     int32_t version = 1;
71     if (!mComposerClient) {
72         return {ScopedAStatus{nullptr}, version};
73     }
74     auto status = mComposerClient->getInterfaceVersion(&version);
75     return {std::move(status), version};
76 }
77 
createVirtualDisplay(int32_t width,int32_t height,PixelFormat pixelFormat,int32_t bufferSlotCount)78 std::pair<ScopedAStatus, VirtualDisplay> VtsComposerClient::createVirtualDisplay(
79         int32_t width, int32_t height, PixelFormat pixelFormat, int32_t bufferSlotCount) {
80     VirtualDisplay outVirtualDisplay;
81     auto status = mComposerClient->createVirtualDisplay(width, height, pixelFormat, bufferSlotCount,
82                                                         &outVirtualDisplay);
83     if (!status.isOk()) {
84         return {std::move(status), outVirtualDisplay};
85     }
86     return {addDisplayToDisplayResources(outVirtualDisplay.display, /*isVirtual*/ true),
87             outVirtualDisplay};
88 }
89 
destroyVirtualDisplay(int64_t display)90 ScopedAStatus VtsComposerClient::destroyVirtualDisplay(int64_t display) {
91     auto status = mComposerClient->destroyVirtualDisplay(display);
92     if (!status.isOk()) {
93         return status;
94     }
95     mDisplayResources.erase(display);
96     return status;
97 }
98 
createLayer(int64_t display,int32_t bufferSlotCount,ComposerClientWriter * writer)99 std::pair<ScopedAStatus, int64_t> VtsComposerClient::createLayer(int64_t display,
100                                                                  int32_t bufferSlotCount,
101                                                                  ComposerClientWriter* writer) {
102     if (mSupportsBatchedCreateLayer) {
103         int64_t layer = mNextLayerHandle++;
104         writer->setLayerLifecycleBatchCommandType(display, layer,
105                                                   LayerLifecycleBatchCommandType::CREATE);
106         writer->setNewBufferSlotCount(display, layer, bufferSlotCount);
107         return {addLayerToDisplayResources(display, layer), layer};
108     }
109 
110     int64_t outLayer;
111     auto status = mComposerClient->createLayer(display, bufferSlotCount, &outLayer);
112 
113     if (!status.isOk()) {
114         return {std::move(status), outLayer};
115     }
116     return {addLayerToDisplayResources(display, outLayer), outLayer};
117 }
118 
destroyLayer(int64_t display,int64_t layer,ComposerClientWriter * writer)119 ScopedAStatus VtsComposerClient::destroyLayer(int64_t display, int64_t layer,
120                                               ComposerClientWriter* writer) {
121     if (mSupportsBatchedCreateLayer) {
122         writer->setLayerLifecycleBatchCommandType(display, layer,
123                                                   LayerLifecycleBatchCommandType::DESTROY);
124     } else {
125         auto status = mComposerClient->destroyLayer(display, layer);
126         if (!status.isOk()) {
127             return status;
128         }
129     }
130 
131     removeLayerFromDisplayResources(display, layer);
132     return ScopedAStatus::ok();
133 }
134 
getActiveConfig(int64_t display)135 std::pair<ScopedAStatus, int32_t> VtsComposerClient::getActiveConfig(int64_t display) {
136     int32_t outConfig;
137     return {mComposerClient->getActiveConfig(display, &outConfig), outConfig};
138 }
139 
setActiveConfig(VtsDisplay * vtsDisplay,int32_t config)140 ScopedAStatus VtsComposerClient::setActiveConfig(VtsDisplay* vtsDisplay, int32_t config) {
141     auto status = mComposerClient->setActiveConfig(vtsDisplay->getDisplayId(), config);
142     if (!status.isOk()) {
143         return status;
144     }
145     return updateDisplayProperties(vtsDisplay, config);
146 }
147 
setPeakRefreshRateConfig(VtsDisplay * vtsDisplay)148 ScopedAStatus VtsComposerClient::setPeakRefreshRateConfig(VtsDisplay* vtsDisplay) {
149     const auto displayId = vtsDisplay->getDisplayId();
150     auto [activeStatus, activeConfig] = getActiveConfig(displayId);
151     EXPECT_TRUE(activeStatus.isOk());
152     auto peakDisplayConfig = vtsDisplay->getDisplayConfig(activeConfig);
153     auto peakConfig = activeConfig;
154 
155     const auto displayConfigs = vtsDisplay->getDisplayConfigs();
156     for (const auto [config, displayConfig] : displayConfigs) {
157         if (displayConfig.configGroup == peakDisplayConfig.configGroup &&
158             displayConfig.vsyncPeriod < peakDisplayConfig.vsyncPeriod) {
159             peakDisplayConfig = displayConfig;
160             peakConfig = config;
161         }
162     }
163     return setActiveConfig(vtsDisplay, peakConfig);
164 }
165 
getDisplayAttribute(int64_t display,int32_t config,DisplayAttribute displayAttribute)166 std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayAttribute(
167         int64_t display, int32_t config, DisplayAttribute displayAttribute) {
168     int32_t outDisplayAttribute;
169     return {mComposerClient->getDisplayAttribute(display, config, displayAttribute,
170                                                  &outDisplayAttribute),
171             outDisplayAttribute};
172 }
173 
setPowerMode(int64_t display,PowerMode powerMode)174 ScopedAStatus VtsComposerClient::setPowerMode(int64_t display, PowerMode powerMode) {
175     return mComposerClient->setPowerMode(display, powerMode);
176 }
177 
setVsync(int64_t display,bool enable)178 ScopedAStatus VtsComposerClient::setVsync(int64_t display, bool enable) {
179     return mComposerClient->setVsyncEnabled(display, enable);
180 }
181 
setVsyncAllowed(bool isAllowed)182 void VtsComposerClient::setVsyncAllowed(bool isAllowed) {
183     mComposerCallback->setVsyncAllowed(isAllowed);
184 }
185 
getDataspaceSaturationMatrix(Dataspace dataspace)186 std::pair<ScopedAStatus, std::vector<float>> VtsComposerClient::getDataspaceSaturationMatrix(
187         Dataspace dataspace) {
188     std::vector<float> outMatrix;
189     return {mComposerClient->getDataspaceSaturationMatrix(dataspace, &outMatrix), outMatrix};
190 }
191 
executeCommands(const std::vector<DisplayCommand> & commands)192 std::pair<ScopedAStatus, std::vector<CommandResultPayload>> VtsComposerClient::executeCommands(
193         const std::vector<DisplayCommand>& commands) {
194     std::vector<CommandResultPayload> outResultPayload;
195     return {mComposerClient->executeCommands(commands, &outResultPayload),
196             std::move(outResultPayload)};
197 }
198 
takeLastVsyncPeriodChangeTimeline()199 std::optional<VsyncPeriodChangeTimeline> VtsComposerClient::takeLastVsyncPeriodChangeTimeline() {
200     return mComposerCallback->takeLastVsyncPeriodChangeTimeline();
201 }
202 
setContentType(int64_t display,ContentType contentType)203 ScopedAStatus VtsComposerClient::setContentType(int64_t display, ContentType contentType) {
204     return mComposerClient->setContentType(display, contentType);
205 }
206 
207 std::pair<ScopedAStatus, VsyncPeriodChangeTimeline>
setActiveConfigWithConstraints(VtsDisplay * vtsDisplay,int32_t config,const VsyncPeriodChangeConstraints & constraints)208 VtsComposerClient::setActiveConfigWithConstraints(VtsDisplay* vtsDisplay, int32_t config,
209                                                   const VsyncPeriodChangeConstraints& constraints) {
210     VsyncPeriodChangeTimeline outTimeline;
211     auto status = mComposerClient->setActiveConfigWithConstraints(
212             vtsDisplay->getDisplayId(), config, constraints, &outTimeline);
213     if (!status.isOk()) {
214         return {std::move(status), outTimeline};
215     }
216     return {updateDisplayProperties(vtsDisplay, config), outTimeline};
217 }
218 
getDisplayCapabilities(int64_t display)219 std::pair<ScopedAStatus, std::vector<DisplayCapability>> VtsComposerClient::getDisplayCapabilities(
220         int64_t display) {
221     std::vector<DisplayCapability> outCapabilities;
222     return {mComposerClient->getDisplayCapabilities(display, &outCapabilities), outCapabilities};
223 }
224 
dumpDebugInfo()225 ScopedAStatus VtsComposerClient::dumpDebugInfo() {
226     int pipefds[2];
227     if (pipe(pipefds) < 0) {
228         return ScopedAStatus::fromServiceSpecificError(IComposer::EX_NO_RESOURCES);
229     }
230 
231     const auto status = mComposer->dump(pipefds[1], /*args*/ nullptr, /*numArgs*/ 0);
232     close(pipefds[0]);
233     close(pipefds[1]);
234     return ScopedAStatus::fromStatus(status);
235 }
236 
getDisplayIdentificationData(int64_t display)237 std::pair<ScopedAStatus, DisplayIdentification> VtsComposerClient::getDisplayIdentificationData(
238         int64_t display) {
239     DisplayIdentification outDisplayIdentification;
240     return {mComposerClient->getDisplayIdentificationData(display, &outDisplayIdentification),
241             outDisplayIdentification};
242 }
243 
getHdrCapabilities(int64_t display)244 std::pair<ScopedAStatus, HdrCapabilities> VtsComposerClient::getHdrCapabilities(int64_t display) {
245     HdrCapabilities outHdrCapabilities;
246     return {mComposerClient->getHdrCapabilities(display, &outHdrCapabilities), outHdrCapabilities};
247 }
248 
249 std::pair<ScopedAStatus, std::vector<PerFrameMetadataKey>>
getPerFrameMetadataKeys(int64_t display)250 VtsComposerClient::getPerFrameMetadataKeys(int64_t display) {
251     std::vector<PerFrameMetadataKey> outPerFrameMetadataKeys;
252     return {mComposerClient->getPerFrameMetadataKeys(display, &outPerFrameMetadataKeys),
253             outPerFrameMetadataKeys};
254 }
255 
getReadbackBufferAttributes(int64_t display)256 std::pair<ScopedAStatus, ReadbackBufferAttributes> VtsComposerClient::getReadbackBufferAttributes(
257         int64_t display) {
258     ReadbackBufferAttributes outReadbackBufferAttributes;
259     return {mComposerClient->getReadbackBufferAttributes(display, &outReadbackBufferAttributes),
260             outReadbackBufferAttributes};
261 }
262 
setReadbackBuffer(int64_t display,const native_handle_t * buffer,const ScopedFileDescriptor & releaseFence)263 ScopedAStatus VtsComposerClient::setReadbackBuffer(int64_t display, const native_handle_t* buffer,
264                                                    const ScopedFileDescriptor& releaseFence) {
265     return mComposerClient->setReadbackBuffer(display, ::android::dupToAidl(buffer), releaseFence);
266 }
267 
getReadbackBufferFence(int64_t display)268 std::pair<ScopedAStatus, ScopedFileDescriptor> VtsComposerClient::getReadbackBufferFence(
269         int64_t display) {
270     ScopedFileDescriptor outReleaseFence;
271     return {mComposerClient->getReadbackBufferFence(display, &outReleaseFence),
272             std::move(outReleaseFence)};
273 }
274 
getColorModes(int64_t display)275 std::pair<ScopedAStatus, std::vector<ColorMode>> VtsComposerClient::getColorModes(int64_t display) {
276     std::vector<ColorMode> outColorModes;
277     return {mComposerClient->getColorModes(display, &outColorModes), outColorModes};
278 }
279 
getRenderIntents(int64_t display,ColorMode colorMode)280 std::pair<ScopedAStatus, std::vector<RenderIntent>> VtsComposerClient::getRenderIntents(
281         int64_t display, ColorMode colorMode) {
282     std::vector<RenderIntent> outRenderIntents;
283     return {mComposerClient->getRenderIntents(display, colorMode, &outRenderIntents),
284             outRenderIntents};
285 }
286 
setColorMode(int64_t display,ColorMode colorMode,RenderIntent renderIntent)287 ScopedAStatus VtsComposerClient::setColorMode(int64_t display, ColorMode colorMode,
288                                               RenderIntent renderIntent) {
289     return mComposerClient->setColorMode(display, colorMode, renderIntent);
290 }
291 
292 std::pair<ScopedAStatus, DisplayContentSamplingAttributes>
getDisplayedContentSamplingAttributes(int64_t display)293 VtsComposerClient::getDisplayedContentSamplingAttributes(int64_t display) {
294     DisplayContentSamplingAttributes outAttributes;
295     return {mComposerClient->getDisplayedContentSamplingAttributes(display, &outAttributes),
296             outAttributes};
297 }
298 
setDisplayedContentSamplingEnabled(int64_t display,bool isEnabled,FormatColorComponent formatColorComponent,int64_t maxFrames)299 ScopedAStatus VtsComposerClient::setDisplayedContentSamplingEnabled(
300         int64_t display, bool isEnabled, FormatColorComponent formatColorComponent,
301         int64_t maxFrames) {
302     return mComposerClient->setDisplayedContentSamplingEnabled(display, isEnabled,
303                                                                formatColorComponent, maxFrames);
304 }
305 
getDisplayedContentSample(int64_t display,int64_t maxFrames,int64_t timestamp)306 std::pair<ScopedAStatus, DisplayContentSample> VtsComposerClient::getDisplayedContentSample(
307         int64_t display, int64_t maxFrames, int64_t timestamp) {
308     DisplayContentSample outDisplayContentSample;
309     return {mComposerClient->getDisplayedContentSample(display, maxFrames, timestamp,
310                                                        &outDisplayContentSample),
311             outDisplayContentSample};
312 }
313 
getDisplayConnectionType(int64_t display)314 std::pair<ScopedAStatus, DisplayConnectionType> VtsComposerClient::getDisplayConnectionType(
315         int64_t display) {
316     DisplayConnectionType outDisplayConnectionType;
317     return {mComposerClient->getDisplayConnectionType(display, &outDisplayConnectionType),
318             outDisplayConnectionType};
319 }
320 
getDisplayConfigs(int64_t display)321 std::pair<ScopedAStatus, std::vector<int32_t>> VtsComposerClient::getDisplayConfigs(
322         int64_t display) {
323     std::vector<int32_t> outConfigs;
324     if (!getDisplayConfigurationSupported()) {
325         return {mComposerClient->getDisplayConfigs(display, &outConfigs), outConfigs};
326     }
327 
328     auto [status, configs] = getDisplayConfigurations(display);
329     if (!status.isOk()) {
330         return {std::move(status), outConfigs};
331     }
332     for (const auto& config : configs) {
333         outConfigs.emplace_back(config.configId);
334     }
335     return {std::move(status), outConfigs};
336 }
337 
338 std::pair<ScopedAStatus, std::vector<DisplayConfiguration>>
getDisplayConfigurations(int64_t display)339 VtsComposerClient::getDisplayConfigurations(int64_t display) {
340     std::vector<DisplayConfiguration> outConfigs;
341     return {mComposerClient->getDisplayConfigurations(display, kMaxFrameIntervalNs, &outConfigs),
342             outConfigs};
343 }
344 
notifyExpectedPresent(int64_t display,ClockMonotonicTimestamp expectedPresentTime,int frameIntervalNs)345 ScopedAStatus VtsComposerClient::notifyExpectedPresent(int64_t display,
346                                                        ClockMonotonicTimestamp expectedPresentTime,
347                                                        int frameIntervalNs) {
348     return mComposerClient->notifyExpectedPresent(display, expectedPresentTime, frameIntervalNs);
349 }
350 
getDisplayVsyncPeriod(int64_t display)351 std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayVsyncPeriod(int64_t display) {
352     int32_t outVsyncPeriodNanos;
353     return {mComposerClient->getDisplayVsyncPeriod(display, &outVsyncPeriodNanos),
354             outVsyncPeriodNanos};
355 }
356 
setAutoLowLatencyMode(int64_t display,bool isEnabled)357 ScopedAStatus VtsComposerClient::setAutoLowLatencyMode(int64_t display, bool isEnabled) {
358     return mComposerClient->setAutoLowLatencyMode(display, isEnabled);
359 }
360 
getSupportedContentTypes(int64_t display)361 std::pair<ScopedAStatus, std::vector<ContentType>> VtsComposerClient::getSupportedContentTypes(
362         int64_t display) {
363     std::vector<ContentType> outContentTypes;
364     return {mComposerClient->getSupportedContentTypes(display, &outContentTypes), outContentTypes};
365 }
366 
367 std::pair<ScopedAStatus, std::optional<DisplayDecorationSupport>>
getDisplayDecorationSupport(int64_t display)368 VtsComposerClient::getDisplayDecorationSupport(int64_t display) {
369     std::optional<DisplayDecorationSupport> outSupport;
370     return {mComposerClient->getDisplayDecorationSupport(display, &outSupport), outSupport};
371 }
372 
getMaxVirtualDisplayCount()373 std::pair<ScopedAStatus, int32_t> VtsComposerClient::getMaxVirtualDisplayCount() {
374     int32_t outMaxVirtualDisplayCount;
375     return {mComposerClient->getMaxVirtualDisplayCount(&outMaxVirtualDisplayCount),
376             outMaxVirtualDisplayCount};
377 }
378 
getDisplayName(int64_t display)379 std::pair<ScopedAStatus, std::string> VtsComposerClient::getDisplayName(int64_t display) {
380     std::string outDisplayName;
381     return {mComposerClient->getDisplayName(display, &outDisplayName), outDisplayName};
382 }
383 
setClientTargetSlotCount(int64_t display,int32_t bufferSlotCount)384 ScopedAStatus VtsComposerClient::setClientTargetSlotCount(int64_t display,
385                                                           int32_t bufferSlotCount) {
386     return mComposerClient->setClientTargetSlotCount(display, bufferSlotCount);
387 }
388 
getCapabilities()389 std::pair<ScopedAStatus, std::vector<Capability>> VtsComposerClient::getCapabilities() {
390     std::vector<Capability> outCapabilities;
391     return {mComposer->getCapabilities(&outCapabilities), outCapabilities};
392 }
393 
setBootDisplayConfig(int64_t display,int32_t config)394 ScopedAStatus VtsComposerClient::setBootDisplayConfig(int64_t display, int32_t config) {
395     return mComposerClient->setBootDisplayConfig(display, config);
396 }
397 
clearBootDisplayConfig(int64_t display)398 ScopedAStatus VtsComposerClient::clearBootDisplayConfig(int64_t display) {
399     return mComposerClient->clearBootDisplayConfig(display);
400 }
401 
getPreferredBootDisplayConfig(int64_t display)402 std::pair<ScopedAStatus, int32_t> VtsComposerClient::getPreferredBootDisplayConfig(
403         int64_t display) {
404     int32_t outConfig;
405     return {mComposerClient->getPreferredBootDisplayConfig(display, &outConfig), outConfig};
406 }
407 
408 std::pair<ScopedAStatus, std::vector<common::HdrConversionCapability>>
getHdrConversionCapabilities()409 VtsComposerClient::getHdrConversionCapabilities() {
410     std::vector<common::HdrConversionCapability> hdrConversionCapability;
411     return {mComposerClient->getHdrConversionCapabilities(&hdrConversionCapability),
412             hdrConversionCapability};
413 }
414 
setHdrConversionStrategy(const common::HdrConversionStrategy & conversionStrategy)415 std::pair<ScopedAStatus, common::Hdr> VtsComposerClient::setHdrConversionStrategy(
416         const common::HdrConversionStrategy& conversionStrategy) {
417     common::Hdr preferredHdrOutputType;
418     return {mComposerClient->setHdrConversionStrategy(conversionStrategy, &preferredHdrOutputType),
419             preferredHdrOutputType};
420 }
421 
getDisplayPhysicalOrientation(int64_t display)422 std::pair<ScopedAStatus, common::Transform> VtsComposerClient::getDisplayPhysicalOrientation(
423         int64_t display) {
424     common::Transform outDisplayOrientation;
425     return {mComposerClient->getDisplayPhysicalOrientation(display, &outDisplayOrientation),
426             outDisplayOrientation};
427 }
428 
getOverlaySupport()429 std::pair<ScopedAStatus, composer3::OverlayProperties> VtsComposerClient::getOverlaySupport() {
430     OverlayProperties properties;
431     return {mComposerClient->getOverlaySupport(&properties), properties};
432 }
433 
setIdleTimerEnabled(int64_t display,int32_t timeoutMs)434 ScopedAStatus VtsComposerClient::setIdleTimerEnabled(int64_t display, int32_t timeoutMs) {
435     return mComposerClient->setIdleTimerEnabled(display, timeoutMs);
436 }
437 
getVsyncIdleCount()438 int32_t VtsComposerClient::getVsyncIdleCount() {
439     return mComposerCallback->getVsyncIdleCount();
440 }
441 
getVsyncIdleTime()442 int64_t VtsComposerClient::getVsyncIdleTime() {
443     return mComposerCallback->getVsyncIdleTime();
444 }
445 
setRefreshRateChangedCallbackDebugEnabled(int64_t display,bool enabled)446 ndk::ScopedAStatus VtsComposerClient::setRefreshRateChangedCallbackDebugEnabled(int64_t display,
447                                                                                 bool enabled) {
448     mComposerCallback->setRefreshRateChangedDebugDataEnabledCallbackAllowed(enabled);
449     return mComposerClient->setRefreshRateChangedCallbackDebugEnabled(display, enabled);
450 }
451 
452 std::vector<RefreshRateChangedDebugData>
takeListOfRefreshRateChangedDebugData()453 VtsComposerClient::takeListOfRefreshRateChangedDebugData() {
454     return mComposerCallback->takeListOfRefreshRateChangedDebugData();
455 }
456 
getInvalidDisplayId()457 int64_t VtsComposerClient::getInvalidDisplayId() {
458     // returns an invalid display id (one that has not been registered to a
459     // display. Currently assuming that a device will never have close to
460     // std::numeric_limit<uint64_t>::max() displays registered while running tests
461     int64_t id = std::numeric_limits<int64_t>::max();
462     std::vector<int64_t> displays = mComposerCallback->getDisplays();
463     while (id > 0) {
464         if (std::none_of(displays.begin(), displays.end(),
465                          [id](const auto& display) { return id == display; })) {
466             return id;
467         }
468         id--;
469     }
470 
471     // Although 0 could be an invalid display, a return value of 0
472     // from getInvalidDisplayId means all other ids are in use, a condition which
473     // we are assuming a device will never have
474     EXPECT_NE(0, id);
475     return id;
476 }
477 
getDisplays()478 std::pair<ScopedAStatus, std::vector<VtsDisplay>> VtsComposerClient::getDisplays() {
479     while (true) {
480         // Sleep for a small period of time to allow all built-in displays
481         // to post hotplug events
482         std::this_thread::sleep_for(5ms);
483         std::vector<int64_t> displays = mComposerCallback->getDisplays();
484         if (displays.empty()) {
485             continue;
486         }
487 
488         std::vector<VtsDisplay> vtsDisplays;
489         vtsDisplays.reserve(displays.size());
490         for (int64_t display : displays) {
491             auto vtsDisplay = VtsDisplay{display};
492             if (getDisplayConfigurationSupported()) {
493                 auto [status, configs] = getDisplayConfigurations(display);
494                 if (!status.isOk()) {
495                     ALOGE("Unable to get the displays for test, failed to get the DisplayConfigs "
496                           "for display %" PRId64,
497                           display);
498                     return {std::move(status), vtsDisplays};
499                 }
500                 addDisplayConfigs(&vtsDisplay, configs);
501             } else {
502                 auto [status, configs] = getDisplayConfigs(display);
503                 if (!status.isOk()) {
504                     ALOGE("Unable to get the displays for test, failed to get the configs "
505                           "for display %" PRId64,
506                           display);
507                     return {std::move(status), vtsDisplays};
508                 }
509                 for (int config : configs) {
510                     status = addDisplayConfigLegacy(&vtsDisplay, config);
511                     if (!status.isOk()) {
512                         ALOGE("Unable to get the displays for test, failed to add config "
513                               "for display %" PRId64,
514                               display);
515                         return {std::move(status), vtsDisplays};
516                     }
517                 }
518             }
519             auto activeConfig = getActiveConfig(display);
520             if (!activeConfig.first.isOk()) {
521                 ALOGE("Unable to get the displays for test, failed to get active config "
522                       "for display %" PRId64,
523                       display);
524                 return {std::move(activeConfig.first), vtsDisplays};
525             }
526             auto status = updateDisplayProperties(&vtsDisplay, activeConfig.second);
527             if (!status.isOk()) {
528                 ALOGE("Unable to get the displays for test, "
529                       "failed to update the properties "
530                       "for display %" PRId64,
531                       display);
532                 return {std::move(status), vtsDisplays};
533             }
534 
535             vtsDisplays.emplace_back(vtsDisplay);
536             addDisplayToDisplayResources(display, /*isVirtual*/ false);
537         }
538 
539         return {ScopedAStatus::ok(), vtsDisplays};
540     }
541 }
542 
addDisplayConfigs(VtsDisplay * vtsDisplay,const std::vector<DisplayConfiguration> & configs)543 void VtsComposerClient::addDisplayConfigs(VtsDisplay* vtsDisplay,
544                                           const std::vector<DisplayConfiguration>& configs) {
545     for (const auto& config : configs) {
546         vtsDisplay->addDisplayConfig(config.configId,
547                                      {config.vsyncPeriod, config.configGroup, config.vrrConfig});
548     }
549 }
550 
addDisplayConfigLegacy(VtsDisplay * vtsDisplay,int32_t config)551 ScopedAStatus VtsComposerClient::addDisplayConfigLegacy(VtsDisplay* vtsDisplay, int32_t config) {
552     const auto vsyncPeriod =
553             getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::VSYNC_PERIOD);
554     const auto configGroup =
555             getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::CONFIG_GROUP);
556     if (vsyncPeriod.first.isOk() && configGroup.first.isOk()) {
557         vtsDisplay->addDisplayConfig(config, {vsyncPeriod.second, configGroup.second});
558         return ScopedAStatus::ok();
559     }
560 
561     LOG(ERROR) << "Failed to update display property vsync: " << vsyncPeriod.first.isOk()
562                << ", config: " << configGroup.first.isOk();
563     return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
564 }
565 
updateDisplayProperties(VtsDisplay * vtsDisplay,int32_t config)566 ScopedAStatus VtsComposerClient::updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config) {
567     if (getDisplayConfigurationSupported()) {
568         auto [status, configs] = getDisplayConfigurations(vtsDisplay->getDisplayId());
569         if (status.isOk()) {
570             for (const auto& displayConfig : configs) {
571                 if (displayConfig.configId == config) {
572                     vtsDisplay->setDimensions(displayConfig.width, displayConfig.height);
573                     return ScopedAStatus::ok();
574                 }
575             }
576         }
577         LOG(ERROR) << "Failed to update display property with DisplayConfig";
578     } else {
579         const auto width =
580                 getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
581         const auto height =
582                 getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
583         if (width.first.isOk() && height.first.isOk()) {
584             vtsDisplay->setDimensions(width.second, height.second);
585             return ScopedAStatus::ok();
586         }
587 
588         LOG(ERROR) << "Failed to update display property for width: " << width.first.isOk()
589                    << ", height: " << height.first.isOk();
590     }
591     return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
592 }
593 
addDisplayToDisplayResources(int64_t display,bool isVirtual)594 ScopedAStatus VtsComposerClient::addDisplayToDisplayResources(int64_t display, bool isVirtual) {
595     if (mDisplayResources.insert({display, DisplayResource(isVirtual)}).second) {
596         return ScopedAStatus::ok();
597     }
598 
599     ALOGE("Duplicate display id %" PRId64, display);
600     return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_DISPLAY);
601 }
602 
addLayerToDisplayResources(int64_t display,int64_t layer)603 ScopedAStatus VtsComposerClient::addLayerToDisplayResources(int64_t display, int64_t layer) {
604     auto resource = mDisplayResources.find(display);
605     if (resource == mDisplayResources.end()) {
606         resource = mDisplayResources.insert({display, DisplayResource(false)}).first;
607     }
608 
609     if (!resource->second.layers.insert(layer).second) {
610         ALOGE("Duplicate layer id %" PRId64, layer);
611         return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_LAYER);
612     }
613     return ScopedAStatus::ok();
614 }
615 
removeLayerFromDisplayResources(int64_t display,int64_t layer)616 void VtsComposerClient::removeLayerFromDisplayResources(int64_t display, int64_t layer) {
617     auto resource = mDisplayResources.find(display);
618     if (resource != mDisplayResources.end()) {
619         resource->second.layers.erase(layer);
620     }
621 }
622 
verifyComposerCallbackParams()623 bool VtsComposerClient::verifyComposerCallbackParams() {
624     bool isValid = true;
625     if (mComposerCallback != nullptr) {
626         if (mComposerCallback->getInvalidHotplugCount() != 0) {
627             ALOGE("Invalid hotplug count");
628             isValid = false;
629         }
630         if (mComposerCallback->getInvalidRefreshCount() != 0) {
631             ALOGE("Invalid refresh count");
632             isValid = false;
633         }
634         if (mComposerCallback->getInvalidVsyncCount() != 0) {
635             ALOGE("Invalid vsync count");
636             isValid = false;
637         }
638         if (mComposerCallback->getInvalidVsyncPeriodChangeCount() != 0) {
639             ALOGE("Invalid vsync period change count");
640             isValid = false;
641         }
642         if (mComposerCallback->getInvalidSeamlessPossibleCount() != 0) {
643             ALOGE("Invalid seamless possible count");
644             isValid = false;
645         }
646         if (mComposerCallback->getInvalidRefreshRateDebugEnabledCallbackCount() != 0) {
647             ALOGE("Invalid refresh rate debug enabled callback count");
648             isValid = false;
649         }
650     }
651     return isValid;
652 }
653 
getDisplayConfigurationSupported() const654 bool VtsComposerClient::getDisplayConfigurationSupported() const {
655     auto [status, interfaceVersion] = getInterfaceVersion();
656     EXPECT_TRUE(status.isOk());
657     // getDisplayConfigurations api is supported starting interface version 3
658     return interfaceVersion >= 3;
659 }
660 
destroyAllLayers(ComposerClientWriter * writer)661 bool VtsComposerClient::destroyAllLayers(ComposerClientWriter* writer) {
662     std::unordered_map<int64_t, DisplayResource> physicalDisplays;
663     while (!mDisplayResources.empty()) {
664         const auto& it = mDisplayResources.begin();
665         const auto& [display, resource] = *it;
666 
667         while (!resource.layers.empty()) {
668             auto layer = *resource.layers.begin();
669             const auto status = destroyLayer(display, layer, writer);
670             if (!status.isOk()) {
671                 ALOGE("Unable to destroy all the layers, failed at layer %" PRId64 " with error %s",
672                       layer, status.getDescription().c_str());
673                 return false;
674             }
675         }
676 
677         if (resource.isVirtual) {
678             const auto status = destroyVirtualDisplay(display);
679             if (!status.isOk()) {
680                 ALOGE("Unable to destroy the display %" PRId64 " failed with error %s", display,
681                       status.getDescription().c_str());
682                 return false;
683             }
684         } else {
685             auto extractIter = mDisplayResources.extract(it);
686             physicalDisplays.insert(std::move(extractIter));
687         }
688     }
689     mDisplayResources.swap(physicalDisplays);
690     mDisplayResources.clear();
691     return true;
692 }
693 }  // namespace aidl::android::hardware::graphics::composer3::vts
694