1 /*
2  * Copyright (C) 2010 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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 
21 // #define LOG_NDEBUG 0
22 
23 #undef LOG_TAG
24 #define LOG_TAG "HWComposer"
25 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
26 
27 #include "HWComposer.h"
28 
29 #include <compositionengine/Output.h>
30 #include <compositionengine/OutputLayer.h>
31 #include <compositionengine/impl/OutputLayerCompositionState.h>
32 #include <log/log.h>
33 #include <ui/DebugUtils.h>
34 #include <ui/GraphicBuffer.h>
35 #include <utils/Errors.h>
36 #include <utils/Trace.h>
37 
38 #include "../Layer.h" // needed only for debugging
39 #include "../Promise.h"
40 #include "../SurfaceFlinger.h"
41 #include "ComposerHal.h"
42 #include "HWC2.h"
43 
44 #define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
45     ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
46 
47 #define LOG_DISPLAY_ERROR(displayId, msg) \
48     ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg)
49 
50 #define LOG_HWC_ERROR(what, error, displayId)                          \
51     ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \
52           to_string(displayId).c_str(), to_string(error).c_str(), static_cast<int32_t>(error))
53 
54 #define RETURN_IF_INVALID_DISPLAY(displayId, ...)            \
55     do {                                                     \
56         if (mDisplayData.count(displayId) == 0) {            \
57             LOG_DISPLAY_ERROR(displayId, "Invalid display"); \
58             return __VA_ARGS__;                              \
59         }                                                    \
60     } while (false)
61 
62 #define RETURN_IF_HWC_ERROR_FOR(what, error, displayId, ...) \
63     do {                                                     \
64         if (error != hal::Error::NONE) {                     \
65             LOG_HWC_ERROR(what, error, displayId);           \
66             return __VA_ARGS__;                              \
67         }                                                    \
68     } while (false)
69 
70 #define RETURN_IF_HWC_ERROR(error, displayId, ...) \
71     RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)
72 
73 namespace hal = android::hardware::graphics::composer::hal;
74 
75 namespace {
76 
77 using android::hardware::Return;
78 using android::hardware::Void;
79 using android::HWC2::ComposerCallback;
80 
81 class ComposerCallbackBridge : public hal::IComposerCallback {
82 public:
ComposerCallbackBridge(ComposerCallback * callback,int32_t sequenceId,bool vsyncSwitchingSupported)83     ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId,
84                            bool vsyncSwitchingSupported)
85           : mCallback(callback),
86             mSequenceId(sequenceId),
87             mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
88 
onHotplug(hal::HWDisplayId display,hal::Connection conn)89     android::hardware::Return<void> onHotplug(hal::HWDisplayId display,
90                                               hal::Connection conn) override {
91         mCallback->onHotplugReceived(mSequenceId, display, conn);
92         return android::hardware::Void();
93     }
94 
onRefresh(hal::HWDisplayId display)95     android::hardware::Return<void> onRefresh(hal::HWDisplayId display) override {
96         mCallback->onRefreshReceived(mSequenceId, display);
97         return android::hardware::Void();
98     }
99 
onVsync(hal::HWDisplayId display,int64_t timestamp)100     android::hardware::Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override {
101         if (!mVsyncSwitchingSupported) {
102             mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
103         } else {
104             ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
105         }
106         return android::hardware::Void();
107     }
108 
onVsync_2_4(hal::HWDisplayId display,int64_t timestamp,hal::VsyncPeriodNanos vsyncPeriodNanos)109     android::hardware::Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp,
110                                                 hal::VsyncPeriodNanos vsyncPeriodNanos) override {
111         if (mVsyncSwitchingSupported) {
112             mCallback->onVsyncReceived(mSequenceId, display, timestamp,
113                                        std::make_optional(vsyncPeriodNanos));
114         } else {
115             ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
116         }
117         return android::hardware::Void();
118     }
119 
onVsyncPeriodTimingChanged(hal::HWDisplayId display,const hal::VsyncPeriodChangeTimeline & updatedTimeline)120     android::hardware::Return<void> onVsyncPeriodTimingChanged(
121             hal::HWDisplayId display,
122             const hal::VsyncPeriodChangeTimeline& updatedTimeline) override {
123         mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, updatedTimeline);
124         return android::hardware::Void();
125     }
126 
onSeamlessPossible(hal::HWDisplayId display)127     android::hardware::Return<void> onSeamlessPossible(hal::HWDisplayId display) override {
128         mCallback->onSeamlessPossible(mSequenceId, display);
129         return android::hardware::Void();
130     }
131 
132 private:
133     ComposerCallback* mCallback;
134     const int32_t mSequenceId;
135     const bool mVsyncSwitchingSupported;
136 };
137 
138 } // namespace
139 
140 namespace android {
141 
142 HWComposer::~HWComposer() = default;
143 
144 namespace impl {
145 
HWComposer(std::unique_ptr<Hwc2::Composer> composer)146 HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) : mComposer(std::move(composer)) {
147 }
148 
HWComposer(const std::string & composerServiceName)149 HWComposer::HWComposer(const std::string& composerServiceName)
150       : mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {
151 }
152 
~HWComposer()153 HWComposer::~HWComposer() {
154     mDisplayData.clear();
155 }
156 
setConfiguration(HWC2::ComposerCallback * callback,int32_t sequenceId)157 void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) {
158     loadCapabilities();
159     loadLayerMetadataSupport();
160 
161     if (mRegisteredCallback) {
162         ALOGW("Callback already registered. Ignored extra registration attempt.");
163         return;
164     }
165     mRegisteredCallback = true;
166     sp<ComposerCallbackBridge> callbackBridge(
167             new ComposerCallbackBridge(callback, sequenceId,
168                                        mComposer->isVsyncPeriodSwitchSupported()));
169     mComposer->registerCallback(callbackBridge);
170 }
171 
getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId,uint8_t * outPort,DisplayIdentificationData * outData) const172 bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
173                                               DisplayIdentificationData* outData) const {
174     const auto error = static_cast<hal::Error>(
175             mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
176     if (error != hal::Error::NONE) {
177         if (error != hal::Error::UNSUPPORTED) {
178             LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
179         }
180         return false;
181     }
182     return true;
183 }
184 
hasCapability(hal::Capability capability) const185 bool HWComposer::hasCapability(hal::Capability capability) const {
186     return mCapabilities.count(capability) > 0;
187 }
188 
hasDisplayCapability(DisplayId displayId,hal::DisplayCapability capability) const189 bool HWComposer::hasDisplayCapability(DisplayId displayId,
190                                       hal::DisplayCapability capability) const {
191     RETURN_IF_INVALID_DISPLAY(displayId, false);
192     return mDisplayData.at(displayId).hwcDisplay->getCapabilities().count(capability) > 0;
193 }
194 
onHotplug(hal::HWDisplayId hwcDisplayId,hal::Connection connection)195 std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
196                                                                hal::Connection connection) {
197     switch (connection) {
198         case hal::Connection::CONNECTED:
199             return onHotplugConnect(hwcDisplayId);
200         case hal::Connection::DISCONNECTED:
201             return onHotplugDisconnect(hwcDisplayId);
202         case hal::Connection::INVALID:
203             return {};
204     }
205 }
206 
onVsync(hal::HWDisplayId hwcDisplayId,int64_t timestamp)207 bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) {
208     const auto displayId = toPhysicalDisplayId(hwcDisplayId);
209     if (!displayId) {
210         LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
211         return false;
212     }
213 
214     RETURN_IF_INVALID_DISPLAY(*displayId, false);
215 
216     auto& displayData = mDisplayData[*displayId];
217     if (displayData.isVirtual) {
218         LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display");
219         return false;
220     }
221 
222     {
223         std::lock_guard lock(displayData.lastHwVsyncLock);
224 
225         // There have been reports of HWCs that signal several vsync events
226         // with the same timestamp when turning the display off and on. This
227         // is a bug in the HWC implementation, but filter the extra events
228         // out here so they don't cause havoc downstream.
229         if (timestamp == displayData.lastHwVsync) {
230             ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
231                   to_string(*displayId).c_str(), timestamp);
232             return false;
233         }
234 
235         displayData.lastHwVsync = timestamp;
236     }
237 
238     const auto tag = "HW_VSYNC_" + to_string(*displayId);
239     ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle);
240     displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
241 
242     return true;
243 }
244 
allocateVirtualDisplay(uint32_t width,uint32_t height,ui::PixelFormat * format)245 std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
246                                                             ui::PixelFormat* format) {
247     if (mRemainingHwcVirtualDisplays == 0) {
248         ALOGE("%s: No remaining virtual displays", __FUNCTION__);
249         return {};
250     }
251 
252     if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
253         (width > SurfaceFlinger::maxVirtualDisplaySize ||
254          height > SurfaceFlinger::maxVirtualDisplaySize)) {
255         ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width,
256               height, SurfaceFlinger::maxVirtualDisplaySize);
257         return {};
258     }
259     hal::HWDisplayId hwcDisplayId = 0;
260     const auto error = static_cast<hal::Error>(
261             mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
262     if (error != hal::Error::NONE) {
263         ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
264         return {};
265     }
266 
267     auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
268                                                          hwcDisplayId, hal::DisplayType::VIRTUAL);
269     display->setConnected(true);
270 
271     DisplayId displayId;
272     if (mFreeVirtualDisplayIds.empty()) {
273         displayId = getVirtualDisplayId(mNextVirtualDisplayId++);
274     } else {
275         displayId = *mFreeVirtualDisplayIds.begin();
276         mFreeVirtualDisplayIds.erase(displayId);
277     }
278 
279     auto& displayData = mDisplayData[displayId];
280     displayData.hwcDisplay = std::move(display);
281     displayData.isVirtual = true;
282 
283     --mRemainingHwcVirtualDisplays;
284     return displayId;
285 }
286 
allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,DisplayId displayId)287 void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) {
288     if (!mInternalHwcDisplayId) {
289         mInternalHwcDisplayId = hwcDisplayId;
290     } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) {
291         mExternalHwcDisplayId = hwcDisplayId;
292     }
293 
294     auto& displayData = mDisplayData[displayId];
295     auto newDisplay =
296             std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
297                                                   hal::DisplayType::PHYSICAL);
298     newDisplay->setConnected(true);
299     displayData.hwcDisplay = std::move(newDisplay);
300     mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
301 }
302 
createLayer(DisplayId displayId)303 HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
304     RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
305 
306     HWC2::Layer* layer;
307     auto error = mDisplayData[displayId].hwcDisplay->createLayer(&layer);
308     RETURN_IF_HWC_ERROR(error, displayId, nullptr);
309     return layer;
310 }
311 
destroyLayer(DisplayId displayId,HWC2::Layer * layer)312 void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) {
313     RETURN_IF_INVALID_DISPLAY(displayId);
314 
315     auto error = mDisplayData[displayId].hwcDisplay->destroyLayer(layer);
316     RETURN_IF_HWC_ERROR(error, displayId);
317 }
318 
getRefreshTimestamp(DisplayId displayId) const319 nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const {
320     RETURN_IF_INVALID_DISPLAY(displayId, 0);
321     const auto& displayData = mDisplayData.at(displayId);
322     // this returns the last refresh timestamp.
323     // if the last one is not available, we estimate it based on
324     // the refresh period and whatever closest timestamp we have.
325     std::lock_guard lock(displayData.lastHwVsyncLock);
326     nsecs_t now = systemTime(CLOCK_MONOTONIC);
327     auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
328     return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
329 }
330 
isConnected(DisplayId displayId) const331 bool HWComposer::isConnected(DisplayId displayId) const {
332     RETURN_IF_INVALID_DISPLAY(displayId, false);
333     return mDisplayData.at(displayId).hwcDisplay->isConnected();
334 }
335 
getConfigs(DisplayId displayId) const336 std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs(
337         DisplayId displayId) const {
338     RETURN_IF_INVALID_DISPLAY(displayId, {});
339 
340     const auto& displayData = mDisplayData.at(displayId);
341     auto configs = displayData.hwcDisplay->getConfigs();
342     if (displayData.configMap.empty()) {
343         for (size_t i = 0; i < configs.size(); ++i) {
344             displayData.configMap[i] = configs[i];
345         }
346     }
347     return configs;
348 }
349 
getActiveConfig(DisplayId displayId) const350 std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig(
351         DisplayId displayId) const {
352     RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
353 
354     std::shared_ptr<const HWC2::Display::Config> config;
355     auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config);
356     if (error == hal::Error::BAD_CONFIG) {
357         LOG_DISPLAY_ERROR(displayId, "No active config");
358         return nullptr;
359     }
360 
361     RETURN_IF_HWC_ERROR(error, displayId, nullptr);
362 
363     if (!config) {
364         LOG_DISPLAY_ERROR(displayId, "Unknown config");
365         return nullptr;
366     }
367 
368     return config;
369 }
370 
371 // Composer 2.4
372 
getDisplayConnectionType(DisplayId displayId) const373 DisplayConnectionType HWComposer::getDisplayConnectionType(DisplayId displayId) const {
374     RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal);
375     const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
376 
377     DisplayConnectionType type;
378     const auto error = hwcDisplay->getConnectionType(&type);
379 
380     const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId
381             ? DisplayConnectionType::Internal
382             : DisplayConnectionType::External;
383 
384     RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
385     return type;
386 }
387 
isVsyncPeriodSwitchSupported(DisplayId displayId) const388 bool HWComposer::isVsyncPeriodSwitchSupported(DisplayId displayId) const {
389     RETURN_IF_INVALID_DISPLAY(displayId, false);
390     return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
391 }
392 
getDisplayVsyncPeriod(DisplayId displayId) const393 nsecs_t HWComposer::getDisplayVsyncPeriod(DisplayId displayId) const {
394     RETURN_IF_INVALID_DISPLAY(displayId, 0);
395 
396     nsecs_t vsyncPeriodNanos;
397     auto error = mDisplayData.at(displayId).hwcDisplay->getDisplayVsyncPeriod(&vsyncPeriodNanos);
398     RETURN_IF_HWC_ERROR(error, displayId, 0);
399     return vsyncPeriodNanos;
400 }
401 
getActiveConfigIndex(DisplayId displayId) const402 int HWComposer::getActiveConfigIndex(DisplayId displayId) const {
403     RETURN_IF_INVALID_DISPLAY(displayId, -1);
404 
405     int index;
406     auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index);
407     if (error == hal::Error::BAD_CONFIG) {
408         LOG_DISPLAY_ERROR(displayId, "No active config");
409         return -1;
410     }
411 
412     RETURN_IF_HWC_ERROR(error, displayId, -1);
413 
414     if (index < 0) {
415         LOG_DISPLAY_ERROR(displayId, "Unknown config");
416         return -1;
417     }
418 
419     return index;
420 }
421 
getColorModes(DisplayId displayId) const422 std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const {
423     RETURN_IF_INVALID_DISPLAY(displayId, {});
424 
425     std::vector<ui::ColorMode> modes;
426     auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
427     RETURN_IF_HWC_ERROR(error, displayId, {});
428     return modes;
429 }
430 
setActiveColorMode(DisplayId displayId,ui::ColorMode mode,ui::RenderIntent renderIntent)431 status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
432                                         ui::RenderIntent renderIntent) {
433     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
434 
435     auto& displayData = mDisplayData[displayId];
436     auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
437     RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
438                              decodeRenderIntent(renderIntent) + ")")
439                                     .c_str(),
440                             error, displayId, UNKNOWN_ERROR);
441 
442     return NO_ERROR;
443 }
444 
setVsyncEnabled(DisplayId displayId,hal::Vsync enabled)445 void HWComposer::setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) {
446     RETURN_IF_INVALID_DISPLAY(displayId);
447     auto& displayData = mDisplayData[displayId];
448 
449     if (displayData.isVirtual) {
450         LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
451         return;
452     }
453 
454     // NOTE: we use our own internal lock here because we have to call
455     // into the HWC with the lock held, and we want to make sure
456     // that even if HWC blocks (which it shouldn't), it won't
457     // affect other threads.
458     std::lock_guard lock(displayData.vsyncEnabledLock);
459     if (enabled == displayData.vsyncEnabled) {
460         return;
461     }
462 
463     ATRACE_CALL();
464     auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
465     RETURN_IF_HWC_ERROR(error, displayId);
466 
467     displayData.vsyncEnabled = enabled;
468 
469     const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
470     ATRACE_INT(tag.c_str(), enabled == hal::Vsync::ENABLE ? 1 : 0);
471 }
472 
setClientTarget(DisplayId displayId,uint32_t slot,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & target,ui::Dataspace dataspace)473 status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
474                                      const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
475                                      ui::Dataspace dataspace) {
476     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
477 
478     ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
479     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
480     auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
481     RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
482     return NO_ERROR;
483 }
484 
getDeviceCompositionChanges(DisplayId displayId,bool frameUsesClientComposition,std::optional<android::HWComposer::DeviceRequestedChanges> * outChanges)485 status_t HWComposer::getDeviceCompositionChanges(
486         DisplayId displayId, bool frameUsesClientComposition,
487         std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
488     ATRACE_CALL();
489 
490     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
491 
492     auto& displayData = mDisplayData[displayId];
493     auto& hwcDisplay = displayData.hwcDisplay;
494     if (!hwcDisplay->isConnected()) {
495         return NO_ERROR;
496     }
497 
498     uint32_t numTypes = 0;
499     uint32_t numRequests = 0;
500 
501     hal::Error error = hal::Error::NONE;
502 
503     // First try to skip validate altogether when there is no client
504     // composition.  When there is client composition, since we haven't
505     // rendered to the client target yet, we should not attempt to skip
506     // validate.
507     displayData.validateWasSkipped = false;
508     if (!frameUsesClientComposition) {
509         sp<Fence> outPresentFence;
510         uint32_t state = UINT32_MAX;
511         error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
512         if (!hasChangesError(error)) {
513             RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
514         }
515         if (state == 1) { //Present Succeeded.
516             std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
517             error = hwcDisplay->getReleaseFences(&releaseFences);
518             displayData.releaseFences = std::move(releaseFences);
519             displayData.lastPresentFence = outPresentFence;
520             displayData.validateWasSkipped = true;
521             displayData.presentError = error;
522             return NO_ERROR;
523         }
524         // Present failed but Validate ran.
525     } else {
526         error = hwcDisplay->validate(&numTypes, &numRequests);
527     }
528     ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
529     if (!hasChangesError(error)) {
530         RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
531     }
532 
533     android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
534     changedTypes.reserve(numTypes);
535     error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
536     RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
537 
538     auto displayRequests = static_cast<hal::DisplayRequest>(0);
539     android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
540     layerRequests.reserve(numRequests);
541     error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
542     RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
543 
544     DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
545     error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
546 
547     outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
548                                                std::move(layerRequests),
549                                                std::move(clientTargetProperty)});
550     error = hwcDisplay->acceptChanges();
551     RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
552 
553     return NO_ERROR;
554 }
555 
getPresentFence(DisplayId displayId) const556 sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const {
557     RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
558     return mDisplayData.at(displayId).lastPresentFence;
559 }
560 
getLayerReleaseFence(DisplayId displayId,HWC2::Layer * layer) const561 sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const {
562     RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
563     const auto& displayFences = mDisplayData.at(displayId).releaseFences;
564     auto fence = displayFences.find(layer);
565     if (fence == displayFences.end()) {
566         ALOGV("getLayerReleaseFence: Release fence not found");
567         return Fence::NO_FENCE;
568     }
569     return fence->second;
570 }
571 
presentAndGetReleaseFences(DisplayId displayId)572 status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
573     ATRACE_CALL();
574 
575     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
576 
577     auto& displayData = mDisplayData[displayId];
578     auto& hwcDisplay = displayData.hwcDisplay;
579 
580     if (displayData.validateWasSkipped) {
581         // explicitly flush all pending commands
582         auto error = static_cast<hal::Error>(mComposer->executeCommands());
583         RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
584         RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
585         return NO_ERROR;
586     }
587 
588     auto error = hwcDisplay->present(&displayData.lastPresentFence);
589     RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
590 
591     std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
592     error = hwcDisplay->getReleaseFences(&releaseFences);
593     RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
594 
595     displayData.releaseFences = std::move(releaseFences);
596 
597     return NO_ERROR;
598 }
599 
setPowerMode(DisplayId displayId,hal::PowerMode mode)600 status_t HWComposer::setPowerMode(DisplayId displayId, hal::PowerMode mode) {
601     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
602 
603     const auto& displayData = mDisplayData[displayId];
604     if (displayData.isVirtual) {
605         LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
606         return INVALID_OPERATION;
607     }
608 
609     if (mode == hal::PowerMode::OFF) {
610         setVsyncEnabled(displayId, hal::Vsync::DISABLE);
611     }
612 
613     auto& hwcDisplay = displayData.hwcDisplay;
614     switch (mode) {
615         case hal::PowerMode::OFF:
616         case hal::PowerMode::ON:
617             ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
618             {
619                 auto error = hwcDisplay->setPowerMode(mode);
620                 if (error != hal::Error::NONE) {
621                     LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
622                                   displayId);
623                 }
624             }
625             break;
626         case hal::PowerMode::DOZE:
627         case hal::PowerMode::DOZE_SUSPEND:
628             ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
629             {
630                 bool supportsDoze = false;
631                 auto error = hwcDisplay->supportsDoze(&supportsDoze);
632                 if (error != hal::Error::NONE) {
633                     LOG_HWC_ERROR("supportsDoze", error, displayId);
634                 }
635 
636                 if (!supportsDoze) {
637                     mode = hal::PowerMode::ON;
638                 }
639 
640                 error = hwcDisplay->setPowerMode(mode);
641                 if (error != hal::Error::NONE) {
642                     LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
643                                   displayId);
644                 }
645             }
646             break;
647         default:
648             ALOGV("setPowerMode: Not calling HWC");
649             break;
650     }
651 
652     return NO_ERROR;
653 }
654 
setActiveConfigWithConstraints(DisplayId displayId,size_t configId,const hal::VsyncPeriodChangeConstraints & constraints,hal::VsyncPeriodChangeTimeline * outTimeline)655 status_t HWComposer::setActiveConfigWithConstraints(
656         DisplayId displayId, size_t configId, const hal::VsyncPeriodChangeConstraints& constraints,
657         hal::VsyncPeriodChangeTimeline* outTimeline) {
658     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
659 
660     auto& displayData = mDisplayData[displayId];
661     if (displayData.configMap.count(configId) == 0) {
662         LOG_DISPLAY_ERROR(displayId, ("Invalid config " + std::to_string(configId)).c_str());
663         return BAD_INDEX;
664     }
665 
666     auto error =
667             displayData.hwcDisplay->setActiveConfigWithConstraints(displayData.configMap[configId],
668                                                                    constraints, outTimeline);
669     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
670     return NO_ERROR;
671 }
672 
setColorTransform(DisplayId displayId,const mat4 & transform)673 status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) {
674     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
675 
676     auto& displayData = mDisplayData[displayId];
677     bool isIdentity = transform == mat4();
678     auto error = displayData.hwcDisplay
679                          ->setColorTransform(transform,
680                                              isIdentity ? hal::ColorTransform::IDENTITY
681                                                         : hal::ColorTransform::ARBITRARY_MATRIX);
682     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
683     return NO_ERROR;
684 }
685 
disconnectDisplay(DisplayId displayId)686 void HWComposer::disconnectDisplay(DisplayId displayId) {
687     RETURN_IF_INVALID_DISPLAY(displayId);
688     auto& displayData = mDisplayData[displayId];
689 
690     // If this was a virtual display, add its slot back for reuse by future
691     // virtual displays
692     if (displayData.isVirtual) {
693         mFreeVirtualDisplayIds.insert(displayId);
694         ++mRemainingHwcVirtualDisplays;
695     }
696 
697     const auto hwcDisplayId = displayData.hwcDisplay->getId();
698 
699     // TODO(b/74619554): Select internal/external display from remaining displays.
700     if (hwcDisplayId == mInternalHwcDisplayId) {
701         mInternalHwcDisplayId.reset();
702     } else if (hwcDisplayId == mExternalHwcDisplayId) {
703         mExternalHwcDisplayId.reset();
704     }
705     mPhysicalDisplayIdMap.erase(hwcDisplayId);
706     mDisplayData.erase(displayId);
707 }
708 
setOutputBuffer(DisplayId displayId,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & buffer)709 status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
710                                      const sp<GraphicBuffer>& buffer) {
711     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
712     const auto& displayData = mDisplayData[displayId];
713 
714     if (!displayData.isVirtual) {
715         LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display");
716         return INVALID_OPERATION;
717     }
718 
719     auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
720     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
721     return NO_ERROR;
722 }
723 
clearReleaseFences(DisplayId displayId)724 void HWComposer::clearReleaseFences(DisplayId displayId) {
725     RETURN_IF_INVALID_DISPLAY(displayId);
726     mDisplayData[displayId].releaseFences.clear();
727 }
728 
getHdrCapabilities(DisplayId displayId,HdrCapabilities * outCapabilities)729 status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) {
730     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
731 
732     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
733     auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
734     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
735     return NO_ERROR;
736 }
737 
getSupportedPerFrameMetadata(DisplayId displayId) const738 int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const {
739     RETURN_IF_INVALID_DISPLAY(displayId, 0);
740     return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
741 }
742 
getRenderIntents(DisplayId displayId,ui::ColorMode colorMode) const743 std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId,
744                                                            ui::ColorMode colorMode) const {
745     RETURN_IF_INVALID_DISPLAY(displayId, {});
746 
747     std::vector<ui::RenderIntent> renderIntents;
748     auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
749     RETURN_IF_HWC_ERROR(error, displayId, {});
750     return renderIntents;
751 }
752 
getDataspaceSaturationMatrix(DisplayId displayId,ui::Dataspace dataspace)753 mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) {
754     RETURN_IF_INVALID_DISPLAY(displayId, {});
755 
756     mat4 matrix;
757     auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
758             &matrix);
759     RETURN_IF_HWC_ERROR(error, displayId, {});
760     return matrix;
761 }
762 
getDisplayedContentSamplingAttributes(DisplayId displayId,ui::PixelFormat * outFormat,ui::Dataspace * outDataspace,uint8_t * outComponentMask)763 status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId,
764                                                            ui::PixelFormat* outFormat,
765                                                            ui::Dataspace* outDataspace,
766                                                            uint8_t* outComponentMask) {
767     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
768     const auto error =
769             mDisplayData[displayId]
770                     .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
771                                                                        outComponentMask);
772     if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
773     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
774     return NO_ERROR;
775 }
776 
setDisplayContentSamplingEnabled(DisplayId displayId,bool enabled,uint8_t componentMask,uint64_t maxFrames)777 status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
778                                                       uint8_t componentMask, uint64_t maxFrames) {
779     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
780     const auto error =
781             mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
782                                                                                  componentMask,
783                                                                                  maxFrames);
784 
785     if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
786     if (error == hal::Error::BAD_PARAMETER) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
787     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
788     return NO_ERROR;
789 }
790 
getDisplayedContentSample(DisplayId displayId,uint64_t maxFrames,uint64_t timestamp,DisplayedFrameStats * outStats)791 status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
792                                                uint64_t timestamp, DisplayedFrameStats* outStats) {
793     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
794     const auto error =
795             mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
796                                                                           outStats);
797     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
798     return NO_ERROR;
799 }
800 
setDisplayBrightness(DisplayId displayId,float brightness)801 std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) {
802     RETURN_IF_INVALID_DISPLAY(displayId, promise::yield<status_t>(BAD_INDEX));
803     auto& display = mDisplayData[displayId].hwcDisplay;
804 
805     return promise::chain(display->setDisplayBrightness(brightness))
806             .then([displayId](hal::Error error) -> status_t {
807                 if (error == hal::Error::UNSUPPORTED) {
808                     RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
809                 }
810                 if (error == hal::Error::BAD_PARAMETER) {
811                     RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
812                 }
813                 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
814                 return NO_ERROR;
815             });
816 }
817 
isUsingVrComposer() const818 bool HWComposer::isUsingVrComposer() const {
819     return getComposer()->isUsingVrComposer();
820 }
821 
setAutoLowLatencyMode(DisplayId displayId,bool on)822 status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) {
823     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
824     const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
825     if (error == hal::Error::UNSUPPORTED) {
826         RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
827     }
828     if (error == hal::Error::BAD_PARAMETER) {
829         RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
830     }
831     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
832     return NO_ERROR;
833 }
834 
getSupportedContentTypes(DisplayId displayId,std::vector<hal::ContentType> * outSupportedContentTypes)835 status_t HWComposer::getSupportedContentTypes(
836         DisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) {
837     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
838     const auto error =
839             mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes);
840 
841     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
842 
843     return NO_ERROR;
844 }
845 
setContentType(DisplayId displayId,hal::ContentType contentType)846 status_t HWComposer::setContentType(DisplayId displayId, hal::ContentType contentType) {
847     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
848     const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
849     if (error == hal::Error::UNSUPPORTED) {
850         RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
851     }
852     if (error == hal::Error::BAD_PARAMETER) {
853         RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
854     }
855     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
856 
857     return NO_ERROR;
858 }
859 
getSupportedLayerGenericMetadata() const860 const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
861     return mSupportedLayerGenericMetadata;
862 }
863 
dump(std::string & result) const864 void HWComposer::dump(std::string& result) const {
865     result.append(mComposer->dumpDebugInfo());
866 }
867 
toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const868 std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const {
869     if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
870         it != mPhysicalDisplayIdMap.end()) {
871         return it->second;
872     }
873     return {};
874 }
875 
fromPhysicalDisplayId(DisplayId displayId) const876 std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const {
877     if (const auto it = mDisplayData.find(displayId);
878         it != mDisplayData.end() && !it->second.isVirtual) {
879         return it->second.hwcDisplay->getId();
880     }
881     return {};
882 }
883 
shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,bool hasDisplayIdentificationData) const884 bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
885                                             bool hasDisplayIdentificationData) const {
886     if (isUsingVrComposer() && mInternalHwcDisplayId) {
887         ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
888         return true;
889     }
890 
891     if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
892         ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
893               hwcDisplayId);
894         return true;
895     }
896 
897     if (!mHasMultiDisplaySupport && mInternalHwcDisplayId && mExternalHwcDisplayId) {
898         ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
899         return true;
900     }
901 
902     return false;
903 }
904 
onHotplugConnect(hal::HWDisplayId hwcDisplayId)905 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
906         hal::HWDisplayId hwcDisplayId) {
907     std::optional<DisplayIdentificationInfo> info;
908     if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
909         info = DisplayIdentificationInfo{.id = *displayId,
910                                          .name = std::string(),
911                                          .deviceProductInfo = std::nullopt};
912     } else {
913         uint8_t port;
914         DisplayIdentificationData data;
915         const bool hasDisplayIdentificationData =
916                 getDisplayIdentificationData(hwcDisplayId, &port, &data);
917         if (mPhysicalDisplayIdMap.empty()) {
918             mHasMultiDisplaySupport = hasDisplayIdentificationData;
919             ALOGI("Switching to %s multi-display mode",
920                   mHasMultiDisplaySupport ? "generalized" : "legacy");
921         }
922 
923         if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
924             return {};
925         }
926 
927         info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
928             const bool isPrimary = !mInternalHwcDisplayId;
929             if (mHasMultiDisplaySupport) {
930                 if (const auto info = parseDisplayIdentificationData(port, data)) {
931                     return *info;
932                 }
933                 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
934             } else {
935                 ALOGW_IF(hasDisplayIdentificationData,
936                          "Ignoring identification data for display %" PRIu64, hwcDisplayId);
937                 port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
938             }
939 
940             return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
941                                              .name = isPrimary ? "Internal display"
942                                                                : "External display",
943                                              .deviceProductInfo = std::nullopt};
944         }();
945     }
946 
947     if (!isConnected(info->id)) {
948         allocatePhysicalDisplay(hwcDisplayId, info->id);
949     }
950     return info;
951 }
952 
onHotplugDisconnect(hal::HWDisplayId hwcDisplayId)953 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
954         hal::HWDisplayId hwcDisplayId) {
955     const auto displayId = toPhysicalDisplayId(hwcDisplayId);
956     if (!displayId) {
957         ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
958         return {};
959     }
960 
961     // The display will later be destroyed by a call to
962     // destroyDisplay(). For now we just mark it disconnected.
963     if (isConnected(*displayId)) {
964         mDisplayData[*displayId].hwcDisplay->setConnected(false);
965     } else {
966         ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
967     }
968     // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
969     // via SurfaceFlinger's onHotplugReceived callback handling
970     return DisplayIdentificationInfo{.id = *displayId,
971                                      .name = std::string(),
972                                      .deviceProductInfo = std::nullopt};
973 }
974 
loadCapabilities()975 void HWComposer::loadCapabilities() {
976     static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
977     auto capabilities = mComposer->getCapabilities();
978     for (auto capability : capabilities) {
979         mCapabilities.emplace(static_cast<hal::Capability>(capability));
980     }
981 }
982 
loadLayerMetadataSupport()983 void HWComposer::loadLayerMetadataSupport() {
984     mSupportedLayerGenericMetadata.clear();
985 
986     std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo;
987     const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo);
988     if (error != hardware::graphics::composer::V2_4::Error::NONE) {
989         ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
990               toString(error).c_str(), static_cast<int32_t>(error));
991         return;
992     }
993 
994     for (const auto& [name, mandatory] : supportedMetadataKeyInfo) {
995         mSupportedLayerGenericMetadata.emplace(name, mandatory);
996     }
997 }
998 
getMaxVirtualDisplayCount() const999 uint32_t HWComposer::getMaxVirtualDisplayCount() const {
1000     return mComposer->getMaxVirtualDisplayCount();
1001 }
1002 
1003 } // namespace impl
1004 } // namespace android
1005 
1006 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1007 #pragma clang diagnostic pop // ignored "-Wconversion"
1008