• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 "Display.h"
18 
19 #include <android-base/parseint.h>
20 #include <android-base/unique_fd.h>
21 #include <pthread.h>
22 #include <sched.h>
23 #include <sync/sync.h>
24 #include <sys/types.h>
25 
26 #include <algorithm>
27 #include <atomic>
28 #include <numeric>
29 #include <sstream>
30 #include <thread>
31 
32 #include "Common.h"
33 #include "Device.h"
34 #include "Time.h"
35 
36 namespace aidl::android::hardware::graphics::composer3::impl {
37 namespace {
38 
isValidColorMode(ColorMode mode)39 bool isValidColorMode(ColorMode mode) {
40     switch (mode) {
41         case ColorMode::NATIVE:
42         case ColorMode::STANDARD_BT601_625:
43         case ColorMode::STANDARD_BT601_625_UNADJUSTED:
44         case ColorMode::STANDARD_BT601_525:
45         case ColorMode::STANDARD_BT601_525_UNADJUSTED:
46         case ColorMode::STANDARD_BT709:
47         case ColorMode::DCI_P3:
48         case ColorMode::SRGB:
49         case ColorMode::ADOBE_RGB:
50         case ColorMode::DISPLAY_P3:
51         case ColorMode::BT2020:
52         case ColorMode::BT2100_PQ:
53         case ColorMode::BT2100_HLG:
54         case ColorMode::DISPLAY_BT2020:
55             return true;
56         default:
57             return false;
58     }
59 }
60 
isValidRenderIntent(RenderIntent intent)61 bool isValidRenderIntent(RenderIntent intent) {
62     switch (intent) {
63         case RenderIntent::COLORIMETRIC:
64         case RenderIntent::ENHANCE:
65         case RenderIntent::TONE_MAP_COLORIMETRIC:
66         case RenderIntent::TONE_MAP_ENHANCE:
67             return true;
68         default:
69             return false;
70     }
71 }
72 
isValidPowerMode(PowerMode mode)73 bool isValidPowerMode(PowerMode mode) {
74     switch (mode) {
75         case PowerMode::OFF:
76         case PowerMode::DOZE:
77         case PowerMode::DOZE_SUSPEND:
78         case PowerMode::ON:
79         case PowerMode::ON_SUSPEND:
80             return true;
81         default:
82             return false;
83     }
84 }
85 
86 }  // namespace
87 
Display(FrameComposer * composer,int64_t id)88 Display::Display(FrameComposer* composer, int64_t id)
89     : mComposer(composer), mId(id), mVsyncThread(id) {
90     setLegacyEdid();
91 }
92 
~Display()93 Display::~Display() {}
94 
init(const std::vector<DisplayConfig> & configs,int32_t activeConfigId,const std::optional<std::vector<uint8_t>> & edid)95 HWC3::Error Display::init(const std::vector<DisplayConfig>& configs, int32_t activeConfigId,
96                           const std::optional<std::vector<uint8_t>>& edid) {
97     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
98 
99     for (const DisplayConfig& config : configs) {
100         mConfigs.emplace(config.getId(), config);
101     }
102 
103     mActiveConfigId = activeConfigId;
104 
105     auto bootConfigIdOpt = getBootConfigId();
106     if (bootConfigIdOpt) {
107         mActiveConfigId = *bootConfigIdOpt;
108     }
109 
110     if (edid.has_value()) {
111         mEdid = *edid;
112     }
113 
114     auto it = mConfigs.find(activeConfigId);
115     if (it == mConfigs.end()) {
116         ALOGE("%s: display:%" PRId64 "missing config:%" PRId32, __FUNCTION__, mId, activeConfigId);
117         return HWC3::Error::NoResources;
118     }
119 
120     const auto& activeConfig = it->second;
121     const auto activeConfigString = activeConfig.toString();
122     ALOGD("%s display:%" PRId64 " with config:%s", __FUNCTION__, mId, activeConfigString.c_str());
123 
124     mVsyncThread.start(activeConfig.getVsyncPeriod());
125 
126     return HWC3::Error::None;
127 }
128 
updateParameters(uint32_t width,uint32_t height,uint32_t dpiX,uint32_t dpiY,uint32_t refreshRateHz,const std::optional<std::vector<uint8_t>> & edid)129 HWC3::Error Display::updateParameters(uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY,
130                                       uint32_t refreshRateHz,
131                                       const std::optional<std::vector<uint8_t>>& edid) {
132     DEBUG_LOG("%s: updating display:%" PRId64
133               " width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
134               __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
135 
136     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
137 
138     auto it = mConfigs.find(*mActiveConfigId);
139     if (it == mConfigs.end()) {
140         ALOGE("%s: failed to find config %" PRId32, __func__, *mActiveConfigId);
141         return HWC3::Error::NoResources;
142     }
143     DisplayConfig& config = it->second;
144     int32_t oldVsyncPeriod = config.getAttribute(DisplayAttribute::VSYNC_PERIOD);
145     int32_t newVsyncPeriod = HertzToPeriodNanos(refreshRateHz);
146     if (oldVsyncPeriod != newVsyncPeriod) {
147         config.setAttribute(DisplayAttribute::VSYNC_PERIOD, newVsyncPeriod);
148 
149         // Schedule a vsync update to propagate across system.
150         VsyncPeriodChangeConstraints constraints;
151         constraints.desiredTimeNanos = 0;
152 
153         VsyncPeriodChangeTimeline timeline;
154 
155         HWC3::Error error =
156             mVsyncThread.scheduleVsyncUpdate(newVsyncPeriod, constraints, &timeline);
157         if (error != HWC3::Error::None) {
158             ALOGE("%s: display:%" PRId64 " composer failed to schedule vsync update", __FUNCTION__,
159                   mId);
160             return error;
161         }
162     }
163     config.setAttribute(DisplayAttribute::WIDTH, static_cast<int32_t>(width));
164     config.setAttribute(DisplayAttribute::HEIGHT, static_cast<int32_t>(height));
165     config.setAttribute(DisplayAttribute::DPI_X, static_cast<int32_t>(dpiX));
166     config.setAttribute(DisplayAttribute::DPI_Y, static_cast<int32_t>(dpiY));
167 
168     if (edid.has_value()) {
169         mEdid = *edid;
170     }
171 
172     return HWC3::Error::None;
173 }
174 
createLayer(int64_t * outLayerId)175 HWC3::Error Display::createLayer(int64_t* outLayerId) {
176     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
177 
178     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
179 
180     auto layer = std::make_unique<Layer>();
181 
182     const int64_t layerId = layer->getId();
183     DEBUG_LOG("%s: created layer:%" PRId64, __FUNCTION__, layerId);
184 
185     mLayers.emplace(layerId, std::move(layer));
186 
187     *outLayerId = layerId;
188 
189     return HWC3::Error::None;
190 }
191 
destroyLayer(int64_t layerId)192 HWC3::Error Display::destroyLayer(int64_t layerId) {
193     DEBUG_LOG("%s: destroy layer:%" PRId64, __FUNCTION__, layerId);
194 
195     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
196 
197     auto it = mLayers.find(layerId);
198     if (it == mLayers.end()) {
199         ALOGE("%s display:%" PRId64 " has no such layer:%." PRId64, __FUNCTION__, mId, layerId);
200         return HWC3::Error::BadLayer;
201     }
202 
203     mOrderedLayers.erase(
204         std::remove_if(mOrderedLayers.begin(),  //
205                        mOrderedLayers.end(),    //
206                        [layerId](Layer* layer) { return layer->getId() == layerId; }),
207         mOrderedLayers.end());
208 
209     mLayers.erase(it);
210 
211     DEBUG_LOG("%s: destroyed layer:%" PRId64, __FUNCTION__, layerId);
212     return HWC3::Error::None;
213 }
214 
getActiveConfig(int32_t * outConfig)215 HWC3::Error Display::getActiveConfig(int32_t* outConfig) {
216     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
217 
218     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
219 
220     if (!mActiveConfigId) {
221         ALOGW("%s: display:%" PRId64 " has no active config.", __FUNCTION__, mId);
222         return HWC3::Error::BadConfig;
223     }
224 
225     *outConfig = *mActiveConfigId;
226     return HWC3::Error::None;
227 }
228 
getDisplayAttribute(int32_t configId,DisplayAttribute attribute,int32_t * outValue)229 HWC3::Error Display::getDisplayAttribute(int32_t configId, DisplayAttribute attribute,
230                                          int32_t* outValue) {
231     auto attributeString = toString(attribute);
232     DEBUG_LOG("%s: display:%" PRId64 " attribute:%s", __FUNCTION__, mId, attributeString.c_str());
233 
234     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
235 
236     auto it = mConfigs.find(configId);
237     if (it == mConfigs.end()) {
238         ALOGW("%s: display:%" PRId64 " bad config:%" PRId32, __FUNCTION__, mId, configId);
239         return HWC3::Error::BadConfig;
240     }
241 
242     const DisplayConfig& config = it->second;
243     *outValue = config.getAttribute(attribute);
244     DEBUG_LOG("%s: display:%" PRId64 " attribute:%s value is %" PRIi32, __FUNCTION__, mId,
245               attributeString.c_str(), *outValue);
246     return HWC3::Error::None;
247 }
248 
getColorModes(std::vector<ColorMode> * outModes)249 HWC3::Error Display::getColorModes(std::vector<ColorMode>* outModes) {
250     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
251 
252     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
253 
254     outModes->clear();
255     outModes->insert(outModes->end(), mColorModes.begin(), mColorModes.end());
256 
257     return HWC3::Error::None;
258 }
259 
getDisplayCapabilities(std::vector<DisplayCapability> * outCapabilities)260 HWC3::Error Display::getDisplayCapabilities(std::vector<DisplayCapability>* outCapabilities) {
261     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
262 
263     outCapabilities->clear();
264     outCapabilities->push_back(DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
265     outCapabilities->push_back(DisplayCapability::MULTI_THREADED_PRESENT);
266 
267     return HWC3::Error::None;
268 }
269 
getDisplayConfigs(std::vector<int32_t> * outConfigIds)270 HWC3::Error Display::getDisplayConfigs(std::vector<int32_t>* outConfigIds) {
271     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
272 
273     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
274 
275     outConfigIds->clear();
276     outConfigIds->reserve(mConfigs.size());
277     for (const auto& [configId, _] : mConfigs) {
278         outConfigIds->push_back(configId);
279     }
280 
281     return HWC3::Error::None;
282 }
283 
getDisplayConfigurations(std::vector<DisplayConfiguration> * outConfigs)284 HWC3::Error Display::getDisplayConfigurations(std::vector<DisplayConfiguration>* outConfigs) {
285     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
286 
287     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
288 
289     outConfigs->clear();
290     outConfigs->reserve(mConfigs.size());
291 
292     for (const auto& [configId, displayConfig] : mConfigs) {
293         DisplayConfiguration displayConfiguration;
294         displayConfiguration.configId = configId;
295         displayConfiguration.width = displayConfig.getWidth();
296         displayConfiguration.height = displayConfig.getHeight();
297         displayConfiguration.dpi = {static_cast<float>(displayConfig.getDpiX()),
298                                     static_cast<float>(displayConfig.getDpiY())};
299         displayConfiguration.vsyncPeriod = displayConfig.getVsyncPeriod();
300         displayConfiguration.configGroup = displayConfig.getConfigGroup();
301         displayConfiguration.hdrOutputType = OutputType::SYSTEM;
302 
303         outConfigs->emplace_back(displayConfiguration);
304     }
305 
306     return HWC3::Error::None;
307 }
308 
getDisplayConnectionType(DisplayConnectionType * outType)309 HWC3::Error Display::getDisplayConnectionType(DisplayConnectionType* outType) {
310     *outType = DisplayConnectionType::INTERNAL;
311     return HWC3::Error::None;
312 }
313 
getDisplayIdentificationData(DisplayIdentification * outIdentification)314 HWC3::Error Display::getDisplayIdentificationData(DisplayIdentification* outIdentification) {
315     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
316 
317     if (outIdentification == nullptr) {
318         return HWC3::Error::BadParameter;
319     }
320 
321     outIdentification->port = static_cast<int8_t>(mId);
322     outIdentification->data = mEdid;
323 
324     return HWC3::Error::None;
325 }
326 
getDisplayName(std::string * outName)327 HWC3::Error Display::getDisplayName(std::string* outName) {
328     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
329 
330     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
331 
332     *outName = mName;
333     return HWC3::Error::None;
334 }
335 
getDisplayVsyncPeriod(int32_t * outVsyncPeriod)336 HWC3::Error Display::getDisplayVsyncPeriod(int32_t* outVsyncPeriod) {
337     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
338 
339     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
340 
341     if (!mActiveConfigId) {
342         ALOGE("%s : display:%" PRId64 " no active config", __FUNCTION__, mId);
343         return HWC3::Error::BadConfig;
344     }
345 
346     const auto it = mConfigs.find(*mActiveConfigId);
347     if (it == mConfigs.end()) {
348         ALOGE("%s : display:%" PRId64 " failed to find active config:%" PRId32, __FUNCTION__, mId,
349               *mActiveConfigId);
350         return HWC3::Error::BadConfig;
351     }
352     const DisplayConfig& activeConfig = it->second;
353 
354     *outVsyncPeriod = activeConfig.getAttribute(DisplayAttribute::VSYNC_PERIOD);
355     return HWC3::Error::None;
356 }
357 
getDisplayedContentSample(int64_t,int64_t,DisplayContentSample *)358 HWC3::Error Display::getDisplayedContentSample(int64_t /*maxFrames*/, int64_t /*timestamp*/,
359                                                DisplayContentSample* /*samples*/) {
360     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
361 
362     return HWC3::Error::Unsupported;
363 }
364 
getDisplayedContentSamplingAttributes(DisplayContentSamplingAttributes *)365 HWC3::Error Display::getDisplayedContentSamplingAttributes(
366     DisplayContentSamplingAttributes* /*outAttributes*/) {
367     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
368 
369     return HWC3::Error::Unsupported;
370 }
371 
getDisplayPhysicalOrientation(common::Transform * outOrientation)372 HWC3::Error Display::getDisplayPhysicalOrientation(common::Transform* outOrientation) {
373     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
374 
375     *outOrientation = common::Transform::NONE;
376 
377     return HWC3::Error::None;
378 }
379 
getHdrCapabilities(HdrCapabilities * outCapabilities)380 HWC3::Error Display::getHdrCapabilities(HdrCapabilities* outCapabilities) {
381     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
382 
383     // No supported types.
384     outCapabilities->types.clear();
385 
386     return HWC3::Error::None;
387 }
388 
getPerFrameMetadataKeys(std::vector<PerFrameMetadataKey> * outKeys)389 HWC3::Error Display::getPerFrameMetadataKeys(std::vector<PerFrameMetadataKey>* outKeys) {
390     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
391 
392     outKeys->clear();
393 
394     return HWC3::Error::Unsupported;
395 }
396 
getReadbackBufferAttributes(ReadbackBufferAttributes * outAttributes)397 HWC3::Error Display::getReadbackBufferAttributes(ReadbackBufferAttributes* outAttributes) {
398     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
399 
400     outAttributes->format = common::PixelFormat::RGBA_8888;
401     outAttributes->dataspace = common::Dataspace::UNKNOWN;
402 
403     return HWC3::Error::Unsupported;
404 }
405 
getReadbackBufferFence(ndk::ScopedFileDescriptor *)406 HWC3::Error Display::getReadbackBufferFence(ndk::ScopedFileDescriptor* /*outAcquireFence*/) {
407     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
408 
409     return HWC3::Error::Unsupported;
410 }
411 
getRenderIntents(ColorMode mode,std::vector<RenderIntent> * outIntents)412 HWC3::Error Display::getRenderIntents(ColorMode mode, std::vector<RenderIntent>* outIntents) {
413     const auto modeString = toString(mode);
414     DEBUG_LOG("%s: display:%" PRId64 "for mode:%s", __FUNCTION__, mId, modeString.c_str());
415 
416     outIntents->clear();
417 
418     if (!isValidColorMode(mode)) {
419         DEBUG_LOG("%s: display:%" PRId64 "invalid mode:%s", __FUNCTION__, mId, modeString.c_str());
420         return HWC3::Error::BadParameter;
421     }
422 
423     outIntents->push_back(RenderIntent::COLORIMETRIC);
424 
425     return HWC3::Error::None;
426 }
427 
getSupportedContentTypes(std::vector<ContentType> * outTypes)428 HWC3::Error Display::getSupportedContentTypes(std::vector<ContentType>* outTypes) {
429     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
430 
431     outTypes->clear();
432 
433     return HWC3::Error::None;
434 }
435 
getDecorationSupport(std::optional<common::DisplayDecorationSupport> * outSupport)436 HWC3::Error Display::getDecorationSupport(
437     std::optional<common::DisplayDecorationSupport>* outSupport) {
438     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
439 
440     outSupport->reset();
441 
442     return HWC3::Error::Unsupported;
443 }
444 
registerCallback(const std::shared_ptr<IComposerCallback> & callback)445 HWC3::Error Display::registerCallback(const std::shared_ptr<IComposerCallback>& callback) {
446     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
447 
448     mVsyncThread.setCallbacks(callback);
449 
450     return HWC3::Error::Unsupported;
451 }
452 
setActiveConfig(int32_t configId)453 HWC3::Error Display::setActiveConfig(int32_t configId) {
454     DEBUG_LOG("%s: display:%" PRId64 " setting active config to %" PRId32, __FUNCTION__, mId,
455               configId);
456 
457     VsyncPeriodChangeConstraints constraints;
458     constraints.desiredTimeNanos = 0;
459     constraints.seamlessRequired = false;
460 
461     VsyncPeriodChangeTimeline timeline;
462 
463     return setActiveConfigWithConstraints(configId, constraints, &timeline);
464 }
465 
setActiveConfigWithConstraints(int32_t configId,const VsyncPeriodChangeConstraints & constraints,VsyncPeriodChangeTimeline * outTimeline)466 HWC3::Error Display::setActiveConfigWithConstraints(int32_t configId,
467                                                     const VsyncPeriodChangeConstraints& constraints,
468                                                     VsyncPeriodChangeTimeline* outTimeline) {
469     DEBUG_LOG("%s: display:%" PRId64 " config:%" PRId32, __FUNCTION__, mId, configId);
470 
471     if (outTimeline == nullptr) {
472         return HWC3::Error::BadParameter;
473     }
474 
475     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
476 
477     if (mActiveConfigId == configId) {
478         return HWC3::Error::None;
479     }
480 
481     DisplayConfig* newConfig = getConfig(configId);
482     if (newConfig == nullptr) {
483         ALOGE("%s: display:%" PRId64 " bad config:%" PRId32, __FUNCTION__, mId, configId);
484         return HWC3::Error::BadConfig;
485     }
486 
487     if (constraints.seamlessRequired) {
488         if (mActiveConfigId) {
489             DisplayConfig* oldConfig = getConfig(*mActiveConfigId);
490             if (oldConfig == nullptr) {
491                 ALOGE("%s: display:%" PRId64 " missing config:%" PRId32, __FUNCTION__, mId,
492                       *mActiveConfigId);
493                 return HWC3::Error::NoResources;
494             }
495 
496             const int32_t newConfigGroup = newConfig->getConfigGroup();
497             const int32_t oldConfigGroup = oldConfig->getConfigGroup();
498             if (newConfigGroup != oldConfigGroup) {
499                 DEBUG_LOG("%s: display:%" PRId64 " config:%" PRId32
500                           " seamless not supported between different config groups "
501                           "old:%d vs new:%d",
502                           __FUNCTION__, mId, configId, oldConfigGroup, newConfigGroup);
503                 return HWC3::Error::SeamlessNotAllowed;
504             }
505         }
506     }
507 
508     mActiveConfigId = configId;
509 
510     if (mComposer == nullptr) {
511         ALOGE("%s: display:%" PRId64 " missing composer", __FUNCTION__, mId);
512         return HWC3::Error::NoResources;
513     }
514 
515     HWC3::Error error = mComposer->onActiveConfigChange(this);
516     if (error != HWC3::Error::None) {
517         ALOGE("%s: display:%" PRId64 " composer failed to handle config change", __FUNCTION__, mId);
518         return error;
519     }
520 
521     int32_t vsyncPeriod;
522     error = getDisplayVsyncPeriod(&vsyncPeriod);
523     if (error != HWC3::Error::None) {
524         ALOGE("%s: display:%" PRId64 " composer failed to handle config change", __FUNCTION__, mId);
525         return error;
526     }
527 
528     return mVsyncThread.scheduleVsyncUpdate(vsyncPeriod, constraints, outTimeline);
529 }
530 
getBootConfigId()531 std::optional<int32_t> Display::getBootConfigId() {
532     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
533 
534     if (!Device::getInstance().persistentKeyValueEnabled()) {
535         ALOGD("%s: persistent boot config is not enabled.", __FUNCTION__);
536         return std::nullopt;
537     }
538 
539     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
540 
541     std::string val;
542     HWC3::Error error = Device::getInstance().getPersistentKeyValue(std::to_string(mId), "", &val);
543     if (error != HWC3::Error::None) {
544         ALOGE("%s: display:%" PRId64 " failed to get persistent boot config", __FUNCTION__, mId);
545         return std::nullopt;
546     }
547 
548     if (val.empty()) {
549         return std::nullopt;
550     }
551 
552     int32_t configId = 0;
553     if (!::android::base::ParseInt(val, &configId)) {
554         ALOGE("%s: display:%" PRId64 " failed to parse persistent boot config from: %s",
555               __FUNCTION__, mId, val.c_str());
556         return std::nullopt;
557     }
558 
559     if (!hasConfig(configId)) {
560         ALOGE("%s: display:%" PRId64 " invalid persistent boot config:%" PRId32, __FUNCTION__, mId,
561               configId);
562         return std::nullopt;
563     }
564 
565     return configId;
566 }
567 
setBootConfig(int32_t configId)568 HWC3::Error Display::setBootConfig(int32_t configId) {
569     DEBUG_LOG("%s: display:%" PRId64 " config:%" PRId32, __FUNCTION__, mId, configId);
570 
571     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
572 
573     DisplayConfig* newConfig = getConfig(configId);
574     if (newConfig == nullptr) {
575         ALOGE("%s: display:%" PRId64 " bad config:%" PRId32, __FUNCTION__, mId, configId);
576         return HWC3::Error::BadConfig;
577     }
578 
579     const std::string key = std::to_string(mId);
580     const std::string val = std::to_string(configId);
581     HWC3::Error error = Device::getInstance().setPersistentKeyValue(key, val);
582     if (error != HWC3::Error::None) {
583         ALOGE("%s: display:%" PRId64 " failed to save persistent boot config", __FUNCTION__, mId);
584         return error;
585     }
586 
587     return HWC3::Error::None;
588 }
589 
clearBootConfig()590 HWC3::Error Display::clearBootConfig() {
591     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
592 
593     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
594 
595     const std::string key = std::to_string(mId);
596     const std::string val = "";
597     HWC3::Error error = Device::getInstance().setPersistentKeyValue(key, val);
598     if (error != HWC3::Error::None) {
599         ALOGE("%s: display:%" PRId64 " failed to save persistent boot config", __FUNCTION__, mId);
600         return error;
601     }
602 
603     return HWC3::Error::None;
604 }
605 
getPreferredBootConfig(int32_t * outConfigId)606 HWC3::Error Display::getPreferredBootConfig(int32_t* outConfigId) {
607     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
608 
609     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
610 
611     std::vector<int32_t> configIds;
612     for (const auto [configId, _] : mConfigs) {
613         configIds.push_back(configId);
614     }
615     *outConfigId = *std::min_element(configIds.begin(), configIds.end());
616 
617     return HWC3::Error::None;
618 }
619 
setAutoLowLatencyMode(bool)620 HWC3::Error Display::setAutoLowLatencyMode(bool /*on*/) {
621     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
622 
623     return HWC3::Error::Unsupported;
624 }
625 
setColorMode(ColorMode mode,RenderIntent intent)626 HWC3::Error Display::setColorMode(ColorMode mode, RenderIntent intent) {
627     const std::string modeString = toString(mode);
628     const std::string intentString = toString(intent);
629     DEBUG_LOG("%s: display:%" PRId64 " setting color mode:%s intent:%s", __FUNCTION__, mId,
630               modeString.c_str(), intentString.c_str());
631 
632     if (!isValidColorMode(mode)) {
633         ALOGE("%s: display:%" PRId64 " invalid color mode:%s", __FUNCTION__, mId,
634               modeString.c_str());
635         return HWC3::Error::BadParameter;
636     }
637 
638     if (!isValidRenderIntent(intent)) {
639         ALOGE("%s: display:%" PRId64 " invalid intent:%s", __FUNCTION__, mId, intentString.c_str());
640         return HWC3::Error::BadParameter;
641     }
642 
643     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
644 
645     if (mColorModes.count(mode) == 0) {
646         ALOGE("%s: display %" PRId64 " mode %s not supported", __FUNCTION__, mId,
647               modeString.c_str());
648         return HWC3::Error::Unsupported;
649     }
650 
651     mActiveColorMode = mode;
652     return HWC3::Error::None;
653 }
654 
setContentType(ContentType contentType)655 HWC3::Error Display::setContentType(ContentType contentType) {
656     auto contentTypeString = toString(contentType);
657     DEBUG_LOG("%s: display:%" PRId64 " content type:%s", __FUNCTION__, mId,
658               contentTypeString.c_str());
659 
660     if (contentType != ContentType::NONE) {
661         return HWC3::Error::Unsupported;
662     }
663 
664     return HWC3::Error::None;
665 }
666 
setDisplayedContentSamplingEnabled(bool,FormatColorComponent,int64_t)667 HWC3::Error Display::setDisplayedContentSamplingEnabled(bool /*enable*/,
668                                                         FormatColorComponent /*componentMask*/,
669                                                         int64_t /*maxFrames*/) {
670     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
671 
672     return HWC3::Error::Unsupported;
673 }
674 
setPowerMode(PowerMode mode)675 HWC3::Error Display::setPowerMode(PowerMode mode) {
676     auto modeString = toString(mode);
677     DEBUG_LOG("%s: display:%" PRId64 " to mode:%s", __FUNCTION__, mId, modeString.c_str());
678 
679     if (!isValidPowerMode(mode)) {
680         ALOGE("%s: display:%" PRId64 " invalid mode:%s", __FUNCTION__, mId, modeString.c_str());
681         return HWC3::Error::BadParameter;
682     }
683 
684     if (mode == PowerMode::DOZE || mode == PowerMode::DOZE_SUSPEND ||
685         mode == PowerMode::ON_SUSPEND) {
686         ALOGE("%s display %" PRId64 " mode:%s not supported", __FUNCTION__, mId,
687               modeString.c_str());
688         return HWC3::Error::Unsupported;
689     }
690 
691     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
692 
693     if (IsCuttlefish()) {
694         if (int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); fd != -1) {
695             std::ostringstream stream;
696             stream << "VIRTUAL_DEVICE_DISPLAY_POWER_MODE_CHANGED display=" << mId
697                    << " mode=" << modeString << std::endl;
698             std::string message = stream.str();
699             write(fd, message.c_str(), message.length());
700             close(fd);
701         }
702     }
703 
704     mPowerMode = mode;
705     return HWC3::Error::None;
706 }
707 
setReadbackBuffer(const buffer_handle_t buffer,const ndk::ScopedFileDescriptor & fence)708 HWC3::Error Display::setReadbackBuffer(const buffer_handle_t buffer,
709                                        const ndk::ScopedFileDescriptor& fence) {
710     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
711 
712     mReadbackBuffer.set(buffer, fence);
713 
714     return HWC3::Error::Unsupported;
715 }
716 
setVsyncEnabled(bool enabled)717 HWC3::Error Display::setVsyncEnabled(bool enabled) {
718     DEBUG_LOG("%s: display:%" PRId64 " setting vsync %s", __FUNCTION__, mId,
719               (enabled ? "on" : "off"));
720 
721     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
722 
723     return mVsyncThread.setVsyncEnabled(enabled);
724 }
725 
setIdleTimerEnabled(int32_t timeoutMs)726 HWC3::Error Display::setIdleTimerEnabled(int32_t timeoutMs) {
727     DEBUG_LOG("%s: display:%" PRId64 " timeout:%" PRId32, __FUNCTION__, mId, timeoutMs);
728 
729     (void)timeoutMs;
730 
731     return HWC3::Error::Unsupported;
732 }
733 
setColorTransform(const std::vector<float> & transformMatrix)734 HWC3::Error Display::setColorTransform(const std::vector<float>& transformMatrix) {
735     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
736 
737     if (transformMatrix.size() < 16) {
738         ALOGE("%s: display:%" PRId64 " has non 4x4 matrix, size:%zu", __FUNCTION__, mId,
739               transformMatrix.size());
740         return HWC3::Error::BadParameter;
741     }
742 
743     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
744 
745     auto& colorTransform = mColorTransform.emplace();
746     std::copy_n(transformMatrix.data(), colorTransform.size(), colorTransform.begin());
747 
748     return HWC3::Error::None;
749 }
750 
setBrightness(float brightness)751 HWC3::Error Display::setBrightness(float brightness) {
752     DEBUG_LOG("%s: display:%" PRId64 " brightness:%f", __FUNCTION__, mId, brightness);
753 
754     if (brightness < 0.0f) {
755         ALOGE("%s: display:%" PRId64 " invalid brightness:%f", __FUNCTION__, mId, brightness);
756         return HWC3::Error::BadParameter;
757     }
758 
759     return HWC3::Error::Unsupported;
760 }
761 
setClientTarget(buffer_handle_t buffer,const ndk::ScopedFileDescriptor & fence,common::Dataspace,const std::vector<common::Rect> &)762 HWC3::Error Display::setClientTarget(buffer_handle_t buffer, const ndk::ScopedFileDescriptor& fence,
763                                      common::Dataspace /*dataspace*/,
764                                      const std::vector<common::Rect>& /*damage*/) {
765     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
766 
767     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
768 
769     mClientTarget.set(buffer, fence);
770 
771     mComposer->onDisplayClientTargetSet(this);
772     return HWC3::Error::None;
773 }
774 
setOutputBuffer(buffer_handle_t,const ndk::ScopedFileDescriptor &)775 HWC3::Error Display::setOutputBuffer(buffer_handle_t /*buffer*/,
776                                      const ndk::ScopedFileDescriptor& /*fence*/) {
777     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
778 
779     // TODO: for virtual display
780     return HWC3::Error::None;
781 }
782 
setExpectedPresentTime(const std::optional<ClockMonotonicTimestamp> & expectedPresentTime)783 HWC3::Error Display::setExpectedPresentTime(
784     const std::optional<ClockMonotonicTimestamp>& expectedPresentTime) {
785     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
786 
787     if (!expectedPresentTime.has_value()) {
788         return HWC3::Error::None;
789     }
790 
791     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
792 
793     mExpectedPresentTime.emplace(asTimePoint(expectedPresentTime->timestampNanos));
794 
795     return HWC3::Error::None;
796 }
797 
validate(DisplayChanges * outChanges)798 HWC3::Error Display::validate(DisplayChanges* outChanges) {
799     ATRACE_CALL();
800 
801     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
802 
803     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
804 
805     mPendingChanges.reset();
806 
807     mOrderedLayers.clear();
808     mOrderedLayers.reserve(mLayers.size());
809     for (auto& [_, layerPtr] : mLayers) {
810         mOrderedLayers.push_back(layerPtr.get());
811     }
812     std::sort(mOrderedLayers.begin(), mOrderedLayers.end(),
813               [](const Layer* layerA, const Layer* layerB) {
814                   const auto zA = layerA->getZOrder();
815                   const auto zB = layerB->getZOrder();
816                   if (zA != zB) {
817                       return zA < zB;
818                   }
819                   return layerA->getId() < layerB->getId();
820               });
821 
822     if (mComposer == nullptr) {
823         ALOGE("%s: display:%" PRId64 " missing composer", __FUNCTION__, mId);
824         return HWC3::Error::NoResources;
825     }
826 
827     HWC3::Error error = mComposer->validateDisplay(this, &mPendingChanges);
828     if (error != HWC3::Error::None) {
829         ALOGE("%s: display:%" PRId64 " failed to validate", __FUNCTION__, mId);
830         return error;
831     }
832 
833     if (mPendingChanges.hasAnyChanges()) {
834         mPresentFlowState = PresentFlowState::WAITING_FOR_ACCEPT;
835         DEBUG_LOG("%s: display:%" PRId64 " now WAITING_FOR_ACCEPT", __FUNCTION__, mId);
836     } else {
837         mPresentFlowState = PresentFlowState::WAITING_FOR_PRESENT;
838         DEBUG_LOG("%s: display:%" PRId64 " now WAITING_FOR_PRESENT", __FUNCTION__, mId);
839     }
840 
841     *outChanges = mPendingChanges;
842     return HWC3::Error::None;
843 }
844 
acceptChanges()845 HWC3::Error Display::acceptChanges() {
846     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
847 
848     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
849 
850     switch (mPresentFlowState) {
851         case PresentFlowState::WAITING_FOR_VALIDATE: {
852             ALOGE("%s: display %" PRId64 " failed, not validated", __FUNCTION__, mId);
853             return HWC3::Error::NotValidated;
854         }
855         case PresentFlowState::WAITING_FOR_ACCEPT:
856         case PresentFlowState::WAITING_FOR_PRESENT: {
857             break;
858         }
859     }
860 
861     if (mPendingChanges.compositionChanges) {
862         const ChangedCompositionTypes& compositionChanges = *mPendingChanges.compositionChanges;
863         for (const ChangedCompositionLayer& compositionChange : compositionChanges.layers) {
864             const auto layerId = compositionChange.layer;
865             const auto layerComposition = compositionChange.composition;
866             auto* layer = getLayer(layerId);
867             if (layer == nullptr) {
868                 ALOGE("%s: display:%" PRId64 " layer:%" PRId64 " dropped before acceptChanges()?",
869                       __FUNCTION__, mId, layerId);
870                 continue;
871             }
872 
873             layer->setCompositionType(layerComposition);
874         }
875     }
876     mPendingChanges.reset();
877 
878     mPresentFlowState = PresentFlowState::WAITING_FOR_PRESENT;
879     DEBUG_LOG("%s: display:%" PRId64 " now WAITING_FOR_PRESENT", __FUNCTION__, mId);
880 
881     return HWC3::Error::None;
882 }
883 
present(::android::base::unique_fd * outDisplayFence,std::unordered_map<int64_t,::android::base::unique_fd> * outLayerFences)884 HWC3::Error Display::present(
885     ::android::base::unique_fd* outDisplayFence,
886     std::unordered_map<int64_t, ::android::base::unique_fd>* outLayerFences) {
887     ATRACE_CALL();
888 
889     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
890 
891     outDisplayFence->reset();
892     outLayerFences->clear();
893 
894     std::unique_lock<std::recursive_mutex> lock(mStateMutex);
895 
896     switch (mPresentFlowState) {
897         case PresentFlowState::WAITING_FOR_VALIDATE: {
898             ALOGE("%s: display %" PRId64 " failed, not validated", __FUNCTION__, mId);
899             return HWC3::Error::NotValidated;
900         }
901         case PresentFlowState::WAITING_FOR_ACCEPT: {
902             ALOGE("%s: display %" PRId64 " failed, changes not accepted", __FUNCTION__, mId);
903             return HWC3::Error::NotValidated;
904         }
905         case PresentFlowState::WAITING_FOR_PRESENT: {
906             break;
907         }
908     }
909     mPresentFlowState = PresentFlowState::WAITING_FOR_VALIDATE;
910     DEBUG_LOG("%s: display:%" PRId64 " now WAITING_FOR_VALIDATE", __FUNCTION__, mId);
911 
912     if (mComposer == nullptr) {
913         ALOGE("%s: display:%" PRId64 " missing composer", __FUNCTION__, mId);
914         return HWC3::Error::NoResources;
915     }
916 
917     return mComposer->presentDisplay(this, outDisplayFence, outLayerFences);
918 }
919 
hasConfig(int32_t configId) const920 bool Display::hasConfig(int32_t configId) const {
921     return mConfigs.find(configId) != mConfigs.end();
922 }
923 
getConfig(int32_t configId)924 DisplayConfig* Display::getConfig(int32_t configId) {
925     auto it = mConfigs.find(configId);
926     if (it != mConfigs.end()) {
927         return &it->second;
928     }
929     return nullptr;
930 }
931 
setEdid(std::vector<uint8_t> edid)932 HWC3::Error Display::setEdid(std::vector<uint8_t> edid) {
933     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
934 
935     mEdid = edid;
936     return HWC3::Error::None;
937 }
938 
setLegacyEdid()939 void Display::setLegacyEdid() {
940     // thess EDIDs are carefully generated according to the EDID spec version 1.3,
941     // more info can be found from the following file:
942     //   frameworks/native/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
943     // approved pnp ids can be found here: https://uefi.org/pnp_id_list
944     // pnp id: GGL, name: EMU_display_0, last byte is checksum
945     // display id is local:8141603649153536
946     static constexpr const std::array<uint8_t, 128> kEdid0 = {
947         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00,
948         0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47,
949         0x98, 0x27, 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
950         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
951         0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
952         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
953         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
954         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
955         0x70, 0x6c, 0x61, 0x79, 0x5f, 0x30, 0x00, 0x4b};
956 
957     // pnp id: GGL, name: EMU_display_1
958     // display id is local:8140900251843329
959     static constexpr const std::array<uint8_t, 128> kEdid1 = {
960         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00,
961         0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47,
962         0x98, 0x27, 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
963         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
964         0x2d, 0x40, 0x58, 0x2c, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
965         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
966         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
967         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
968         0x70, 0x6c, 0x61, 0x79, 0x5f, 0x31, 0x00, 0x3b};
969 
970     // pnp id: GGL, name: EMU_display_2
971     // display id is local:8140940453066754
972     static constexpr const std::array<uint8_t, 128> kEdid2 = {
973         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00,
974         0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47,
975         0x98, 0x27, 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
976         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
977         0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
978         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
979         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
980         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
981         0x70, 0x6c, 0x61, 0x79, 0x5f, 0x32, 0x00, 0x49};
982 
983     mEdid.clear();
984     switch (mId) {
985         case 0: {
986             mEdid.insert(mEdid.end(), kEdid0.begin(), kEdid0.end());
987             break;
988         }
989         case 1: {
990             mEdid.insert(mEdid.end(), kEdid1.begin(), kEdid1.end());
991             break;
992         }
993         case 2: {
994             mEdid.insert(mEdid.end(), kEdid2.begin(), kEdid2.end());
995             break;
996         }
997         default: {
998             mEdid.insert(mEdid.end(), kEdid2.begin(), kEdid2.end());
999             const size_t size = mEdid.size();
1000             // Update the name to EMU_display_<mID>
1001             mEdid[size - 3] = '0' + (uint8_t)mId;
1002             // Update the checksum byte
1003             uint8_t checksum = -(uint8_t)std::accumulate(mEdid.data(), mEdid.data() + size - 1,
1004                                                          static_cast<uint8_t>(0));
1005             mEdid[size - 1] = checksum;
1006             break;
1007         }
1008     }
1009 }
1010 
getLayer(int64_t layerId)1011 Layer* Display::getLayer(int64_t layerId) {
1012     auto it = mLayers.find(layerId);
1013     if (it == mLayers.end()) {
1014         ALOGE("%s Unknown layer:%" PRId64, __FUNCTION__, layerId);
1015         return nullptr;
1016     }
1017 
1018     return it->second.get();
1019 }
1020 
waitAndGetClientTargetBuffer()1021 buffer_handle_t Display::waitAndGetClientTargetBuffer() {
1022     DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
1023 
1024     ::android::base::unique_fd fence = mClientTarget.getFence();
1025     if (fence.ok()) {
1026         int err = sync_wait(fence.get(), 3000);
1027         if (err < 0 && errno == ETIME) {
1028             ALOGE("%s waited on fence %" PRId32 " for 3000 ms", __FUNCTION__, fence.get());
1029         }
1030     }
1031 
1032     return mClientTarget.getBuffer();
1033 }
1034 
1035 }  // namespace aidl::android::hardware::graphics::composer3::impl
1036