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