• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,std::optional<PhysicalDisplayId> mirror)247 bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size resolution,
248                                         ui::PixelFormat* format,
249                                         std::optional<PhysicalDisplayId> mirror) {
250     if (!resolution.isValid()) {
251         ALOGE("%s: Invalid resolution %dx%d", __func__, resolution.width, resolution.height);
252         return false;
253     }
254 
255     const uint32_t width = static_cast<uint32_t>(resolution.width);
256     const uint32_t height = static_cast<uint32_t>(resolution.height);
257 
258     if (mMaxVirtualDisplayDimension > 0 &&
259         (width > mMaxVirtualDisplayDimension || height > mMaxVirtualDisplayDimension)) {
260         ALOGE("%s: Resolution %ux%u exceeds maximum dimension %zu", __func__, width, height,
261               mMaxVirtualDisplayDimension);
262         return false;
263     }
264 
265     std::optional<hal::HWDisplayId> hwcMirrorId;
266     if (mirror) {
267         hwcMirrorId = fromPhysicalDisplayId(*mirror);
268     }
269 
270     hal::HWDisplayId hwcDisplayId;
271     const auto error = static_cast<hal::Error>(
272             mComposer->createVirtualDisplay(width, height, format, hwcMirrorId, &hwcDisplayId));
273     RETURN_IF_HWC_ERROR_FOR("createVirtualDisplay", error, displayId, false);
274 
275     auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
276                                                          hwcDisplayId, hal::DisplayType::VIRTUAL);
277     display->setConnected(true);
278     auto& displayData = mDisplayData[displayId];
279     displayData.hwcDisplay = std::move(display);
280     displayData.isVirtual = true;
281     return true;
282 }
283 
allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,PhysicalDisplayId displayId)284 void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,
285                                          PhysicalDisplayId displayId) {
286     mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
287 
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 }
301 
getAttribute(hal::HWDisplayId hwcDisplayId,hal::HWConfigId configId,hal::Attribute attribute) const302 int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
303                                  hal::Attribute attribute) const {
304     int32_t value = 0;
305     auto error = static_cast<hal::Error>(
306             mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
307 
308     RETURN_IF_HWC_ERROR_FOR("getDisplayAttribute", error, *toPhysicalDisplayId(hwcDisplayId), -1);
309     return value;
310 }
311 
createLayer(HalDisplayId displayId)312 std::shared_ptr<HWC2::Layer> HWComposer::createLayer(HalDisplayId displayId) {
313     RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
314 
315     auto expected = mDisplayData[displayId].hwcDisplay->createLayer();
316     if (!expected.has_value()) {
317         auto error = std::move(expected).error();
318         RETURN_IF_HWC_ERROR(error, displayId, nullptr);
319     }
320     return std::move(expected).value();
321 }
322 
isConnected(PhysicalDisplayId displayId) const323 bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
324     if (mDisplayData.count(displayId)) {
325         return mDisplayData.at(displayId).hwcDisplay->isConnected();
326     }
327 
328     return false;
329 }
330 
getModes(PhysicalDisplayId displayId) const331 std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const {
332     RETURN_IF_INVALID_DISPLAY(displayId, {});
333 
334     const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
335     std::vector<hal::HWConfigId> configIds;
336     auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
337     RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
338 
339     std::vector<HWCDisplayMode> modes;
340     modes.reserve(configIds.size());
341     for (auto configId : configIds) {
342         modes.push_back(HWCDisplayMode{
343                 .hwcId = configId,
344                 .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
345                 .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
346                 .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
347                 .dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X),
348                 .dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y),
349                 .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
350         });
351     }
352 
353     return modes;
354 }
355 
getActiveMode(PhysicalDisplayId displayId) const356 std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
357     RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
358 
359     const auto hwcId = *fromPhysicalDisplayId(displayId);
360     ALOGV("[%" PRIu64 "] getActiveMode", hwcId);
361     hal::HWConfigId configId;
362     auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
363 
364     if (error == hal::Error::BAD_CONFIG) {
365         LOG_DISPLAY_ERROR(displayId, "No active mode");
366         return std::nullopt;
367     }
368 
369     return configId;
370 }
371 
372 // Composer 2.4
373 
getDisplayConnectionType(PhysicalDisplayId displayId) const374 ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
375     RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal);
376     const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
377 
378     ui::DisplayConnectionType type;
379     const auto error = hwcDisplay->getConnectionType(&type);
380 
381     const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId
382             ? ui::DisplayConnectionType::Internal
383             : ui::DisplayConnectionType::External;
384 
385     RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
386     return type;
387 }
388 
isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const389 bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const {
390     RETURN_IF_INVALID_DISPLAY(displayId, false);
391     return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
392 }
393 
getDisplayVsyncPeriod(PhysicalDisplayId displayId,nsecs_t * outVsyncPeriod) const394 status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId,
395                                            nsecs_t* outVsyncPeriod) const {
396     RETURN_IF_INVALID_DISPLAY(displayId, 0);
397 
398     if (!isVsyncPeriodSwitchSupported(displayId)) {
399         return INVALID_OPERATION;
400     }
401     const auto hwcId = *fromPhysicalDisplayId(displayId);
402     Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
403     auto error =
404             static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
405     RETURN_IF_HWC_ERROR(error, displayId, 0);
406     *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
407     return NO_ERROR;
408 }
409 
getColorModes(PhysicalDisplayId displayId) const410 std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
411     RETURN_IF_INVALID_DISPLAY(displayId, {});
412 
413     std::vector<ui::ColorMode> modes;
414     auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
415     RETURN_IF_HWC_ERROR(error, displayId, {});
416     return modes;
417 }
418 
setActiveColorMode(PhysicalDisplayId displayId,ui::ColorMode mode,ui::RenderIntent renderIntent)419 status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode,
420                                         ui::RenderIntent renderIntent) {
421     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
422 
423     auto& displayData = mDisplayData[displayId];
424     auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
425     RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
426                              decodeRenderIntent(renderIntent) + ")")
427                                     .c_str(),
428                             error, displayId, UNKNOWN_ERROR);
429 
430     return NO_ERROR;
431 }
432 
setVsyncEnabled(PhysicalDisplayId displayId,hal::Vsync enabled)433 void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) {
434     RETURN_IF_INVALID_DISPLAY(displayId);
435     auto& displayData = mDisplayData[displayId];
436 
437     LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s",
438                  __FUNCTION__, to_string(displayId).c_str());
439 
440     // NOTE: we use our own internal lock here because we have to call
441     // into the HWC with the lock held, and we want to make sure
442     // that even if HWC blocks (which it shouldn't), it won't
443     // affect other threads.
444     std::lock_guard lock(displayData.vsyncEnabledLock);
445     if (enabled == displayData.vsyncEnabled) {
446         return;
447     }
448 
449     ATRACE_CALL();
450     auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
451     RETURN_IF_HWC_ERROR(error, displayId);
452 
453     displayData.vsyncEnabled = enabled;
454 
455     const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
456     ATRACE_INT(tag.c_str(), enabled == hal::Vsync::ENABLE ? 1 : 0);
457 }
458 
setClientTarget(HalDisplayId displayId,uint32_t slot,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & target,ui::Dataspace dataspace)459 status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot,
460                                      const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
461                                      ui::Dataspace dataspace) {
462     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
463 
464     ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
465     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
466     auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
467     RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
468     return NO_ERROR;
469 }
470 
getDeviceCompositionChanges(HalDisplayId displayId,bool frameUsesClientComposition,std::chrono::steady_clock::time_point earliestPresentTime,const std::shared_ptr<FenceTime> & previousPresentFence,std::optional<android::HWComposer::DeviceRequestedChanges> * outChanges)471 status_t HWComposer::getDeviceCompositionChanges(
472         HalDisplayId displayId, bool frameUsesClientComposition,
473         std::chrono::steady_clock::time_point earliestPresentTime,
474         const std::shared_ptr<FenceTime>& previousPresentFence,
475         std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
476     ATRACE_CALL();
477 
478     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
479 
480     auto& displayData = mDisplayData[displayId];
481     auto& hwcDisplay = displayData.hwcDisplay;
482     if (!hwcDisplay->isConnected()) {
483         return NO_ERROR;
484     }
485 
486     uint32_t numTypes = 0;
487     uint32_t numRequests = 0;
488 
489     hal::Error error = hal::Error::NONE;
490 
491     // First try to skip validate altogether. We can do that when
492     // 1. The previous frame has not been presented yet or already passed the
493     // earliest time to present. Otherwise, we may present a frame too early.
494     // 2. There is no client composition. Otherwise, we first need to render the
495     // client target buffer.
496     const bool prevFencePending =
497             previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
498     const bool canPresentEarly =
499             !prevFencePending && std::chrono::steady_clock::now() < earliestPresentTime;
500     const bool canSkipValidate = !canPresentEarly && !frameUsesClientComposition;
501     displayData.validateWasSkipped = false;
502     if (canSkipValidate) {
503         sp<Fence> outPresentFence;
504         uint32_t state = UINT32_MAX;
505         error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
506         if (!hasChangesError(error)) {
507             RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
508         }
509         if (state == 1) { //Present Succeeded.
510             std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
511             error = hwcDisplay->getReleaseFences(&releaseFences);
512             displayData.releaseFences = std::move(releaseFences);
513             displayData.lastPresentFence = outPresentFence;
514             displayData.validateWasSkipped = true;
515             displayData.presentError = error;
516             return NO_ERROR;
517         }
518         // Present failed but Validate ran.
519     } else {
520         error = hwcDisplay->validate(&numTypes, &numRequests);
521     }
522     ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
523     if (!hasChangesError(error)) {
524         RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
525     }
526 
527     android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
528     changedTypes.reserve(numTypes);
529     error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
530     RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
531 
532     auto displayRequests = static_cast<hal::DisplayRequest>(0);
533     android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
534     layerRequests.reserve(numRequests);
535     error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
536     RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
537 
538     DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
539     error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
540 
541     outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
542                                                std::move(layerRequests),
543                                                std::move(clientTargetProperty)});
544     error = hwcDisplay->acceptChanges();
545     RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
546 
547     return NO_ERROR;
548 }
549 
getPresentFence(HalDisplayId displayId) const550 sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const {
551     RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
552     return mDisplayData.at(displayId).lastPresentFence;
553 }
554 
getLayerReleaseFence(HalDisplayId displayId,HWC2::Layer * layer) const555 sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
556     RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
557     const auto& displayFences = mDisplayData.at(displayId).releaseFences;
558     auto fence = displayFences.find(layer);
559     if (fence == displayFences.end()) {
560         ALOGV("getLayerReleaseFence: Release fence not found");
561         return Fence::NO_FENCE;
562     }
563     return fence->second;
564 }
565 
presentAndGetReleaseFences(HalDisplayId displayId,std::chrono::steady_clock::time_point earliestPresentTime,const std::shared_ptr<FenceTime> & previousPresentFence)566 status_t HWComposer::presentAndGetReleaseFences(
567         HalDisplayId displayId, std::chrono::steady_clock::time_point earliestPresentTime,
568         const std::shared_ptr<FenceTime>& previousPresentFence) {
569     ATRACE_CALL();
570 
571     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
572 
573     auto& displayData = mDisplayData[displayId];
574     auto& hwcDisplay = displayData.hwcDisplay;
575 
576     if (displayData.validateWasSkipped) {
577         // explicitly flush all pending commands
578         auto error = static_cast<hal::Error>(mComposer->executeCommands());
579         RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
580         RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
581         return NO_ERROR;
582     }
583 
584     const bool previousFramePending =
585             previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
586     if (!previousFramePending) {
587         ATRACE_NAME("wait for earliest present time");
588         std::this_thread::sleep_until(earliestPresentTime);
589     }
590 
591     auto error = hwcDisplay->present(&displayData.lastPresentFence);
592     RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
593 
594     std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
595     error = hwcDisplay->getReleaseFences(&releaseFences);
596     RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
597 
598     displayData.releaseFences = std::move(releaseFences);
599 
600     return NO_ERROR;
601 }
602 
setPowerMode(PhysicalDisplayId displayId,hal::PowerMode mode)603 status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
604     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
605 
606     const auto& displayData = mDisplayData[displayId];
607     LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s",
608                  __FUNCTION__, to_string(displayId).c_str());
609 
610     if (mode == hal::PowerMode::OFF) {
611         setVsyncEnabled(displayId, hal::Vsync::DISABLE);
612     }
613 
614     auto& hwcDisplay = displayData.hwcDisplay;
615     switch (mode) {
616         case hal::PowerMode::OFF:
617         case hal::PowerMode::ON:
618             ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
619             {
620                 auto error = hwcDisplay->setPowerMode(mode);
621                 if (error != hal::Error::NONE) {
622                     LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
623                                   displayId);
624                 }
625             }
626             break;
627         case hal::PowerMode::DOZE:
628         case hal::PowerMode::DOZE_SUSPEND:
629             ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
630             {
631                 bool supportsDoze = false;
632                 auto error = hwcDisplay->supportsDoze(&supportsDoze);
633                 if (error != hal::Error::NONE) {
634                     LOG_HWC_ERROR("supportsDoze", error, displayId);
635                 }
636 
637                 if (!supportsDoze) {
638                     mode = hal::PowerMode::ON;
639                 }
640 
641                 error = hwcDisplay->setPowerMode(mode);
642                 if (error != hal::Error::NONE) {
643                     LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
644                                   displayId);
645                 }
646             }
647             break;
648         default:
649             ALOGV("setPowerMode: Not calling HWC");
650             break;
651     }
652 
653     return NO_ERROR;
654 }
655 
setActiveModeWithConstraints(PhysicalDisplayId displayId,hal::HWConfigId hwcModeId,const hal::VsyncPeriodChangeConstraints & constraints,hal::VsyncPeriodChangeTimeline * outTimeline)656 status_t HWComposer::setActiveModeWithConstraints(
657         PhysicalDisplayId displayId, hal::HWConfigId hwcModeId,
658         const hal::VsyncPeriodChangeConstraints& constraints,
659         hal::VsyncPeriodChangeTimeline* outTimeline) {
660     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
661 
662     auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
663                                                                                     constraints,
664                                                                                     outTimeline);
665     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
666     return NO_ERROR;
667 }
668 
setColorTransform(HalDisplayId displayId,const mat4 & transform)669 status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) {
670     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
671 
672     auto& displayData = mDisplayData[displayId];
673     bool isIdentity = transform == mat4();
674     auto error = displayData.hwcDisplay
675                          ->setColorTransform(transform,
676                                              isIdentity ? hal::ColorTransform::IDENTITY
677                                                         : hal::ColorTransform::ARBITRARY_MATRIX);
678     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
679     return NO_ERROR;
680 }
681 
disconnectDisplay(HalDisplayId displayId)682 void HWComposer::disconnectDisplay(HalDisplayId displayId) {
683     RETURN_IF_INVALID_DISPLAY(displayId);
684     auto& displayData = mDisplayData[displayId];
685     const auto hwcDisplayId = displayData.hwcDisplay->getId();
686 
687     // TODO(b/74619554): Select internal/external display from remaining displays.
688     if (hwcDisplayId == mInternalHwcDisplayId) {
689         mInternalHwcDisplayId.reset();
690     } else if (hwcDisplayId == mExternalHwcDisplayId) {
691         mExternalHwcDisplayId.reset();
692     }
693     mPhysicalDisplayIdMap.erase(hwcDisplayId);
694     mDisplayData.erase(displayId);
695 }
696 
setOutputBuffer(HalVirtualDisplayId displayId,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & buffer)697 status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
698                                      const sp<GraphicBuffer>& buffer) {
699     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
700     const auto& displayData = mDisplayData[displayId];
701 
702     LOG_FATAL_IF(!displayData.isVirtual, "%s: Invalid operation on physical display with ID %s",
703                  __FUNCTION__, to_string(displayId).c_str());
704 
705     auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
706     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
707     return NO_ERROR;
708 }
709 
clearReleaseFences(HalDisplayId displayId)710 void HWComposer::clearReleaseFences(HalDisplayId displayId) {
711     RETURN_IF_INVALID_DISPLAY(displayId);
712     mDisplayData[displayId].releaseFences.clear();
713 }
714 
getHdrCapabilities(HalDisplayId displayId,HdrCapabilities * outCapabilities)715 status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) {
716     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
717 
718     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
719     auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
720     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
721     return NO_ERROR;
722 }
723 
getSupportedPerFrameMetadata(HalDisplayId displayId) const724 int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const {
725     RETURN_IF_INVALID_DISPLAY(displayId, 0);
726     return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
727 }
728 
getRenderIntents(HalDisplayId displayId,ui::ColorMode colorMode) const729 std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId,
730                                                            ui::ColorMode colorMode) const {
731     RETURN_IF_INVALID_DISPLAY(displayId, {});
732 
733     std::vector<ui::RenderIntent> renderIntents;
734     auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
735     RETURN_IF_HWC_ERROR(error, displayId, {});
736     return renderIntents;
737 }
738 
getDataspaceSaturationMatrix(HalDisplayId displayId,ui::Dataspace dataspace)739 mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) {
740     RETURN_IF_INVALID_DISPLAY(displayId, {});
741 
742     mat4 matrix;
743     auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
744             &matrix);
745     RETURN_IF_HWC_ERROR(error, displayId, {});
746     return matrix;
747 }
748 
getDisplayedContentSamplingAttributes(HalDisplayId displayId,ui::PixelFormat * outFormat,ui::Dataspace * outDataspace,uint8_t * outComponentMask)749 status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId,
750                                                            ui::PixelFormat* outFormat,
751                                                            ui::Dataspace* outDataspace,
752                                                            uint8_t* outComponentMask) {
753     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
754     const auto error =
755             mDisplayData[displayId]
756                     .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
757                                                                        outComponentMask);
758     if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
759     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
760     return NO_ERROR;
761 }
762 
setDisplayContentSamplingEnabled(HalDisplayId displayId,bool enabled,uint8_t componentMask,uint64_t maxFrames)763 status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled,
764                                                       uint8_t componentMask, uint64_t maxFrames) {
765     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
766     const auto error =
767             mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
768                                                                                  componentMask,
769                                                                                  maxFrames);
770 
771     if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
772     if (error == hal::Error::BAD_PARAMETER) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
773     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
774     return NO_ERROR;
775 }
776 
getDisplayedContentSample(HalDisplayId displayId,uint64_t maxFrames,uint64_t timestamp,DisplayedFrameStats * outStats)777 status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames,
778                                                uint64_t timestamp, DisplayedFrameStats* outStats) {
779     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
780     const auto error =
781             mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
782                                                                           outStats);
783     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
784     return NO_ERROR;
785 }
786 
setDisplayBrightness(PhysicalDisplayId displayId,float brightness)787 std::future<status_t> HWComposer::setDisplayBrightness(PhysicalDisplayId displayId,
788                                                        float brightness) {
789     RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX));
790     auto& display = mDisplayData[displayId].hwcDisplay;
791 
792     return ftl::chain(display->setDisplayBrightness(brightness))
793             .then([displayId](hal::Error error) -> status_t {
794                 if (error == hal::Error::UNSUPPORTED) {
795                     RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
796                 }
797                 if (error == hal::Error::BAD_PARAMETER) {
798                     RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
799                 }
800                 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
801                 return NO_ERROR;
802             });
803 }
804 
setAutoLowLatencyMode(PhysicalDisplayId displayId,bool on)805 status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
806     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
807     const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
808     if (error == hal::Error::UNSUPPORTED) {
809         RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
810     }
811     if (error == hal::Error::BAD_PARAMETER) {
812         RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
813     }
814     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
815     return NO_ERROR;
816 }
817 
getSupportedContentTypes(PhysicalDisplayId displayId,std::vector<hal::ContentType> * outSupportedContentTypes)818 status_t HWComposer::getSupportedContentTypes(
819         PhysicalDisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) {
820     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
821     const auto error =
822             mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes);
823 
824     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
825 
826     return NO_ERROR;
827 }
828 
setContentType(PhysicalDisplayId displayId,hal::ContentType contentType)829 status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) {
830     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
831     const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
832     if (error == hal::Error::UNSUPPORTED) {
833         RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
834     }
835     if (error == hal::Error::BAD_PARAMETER) {
836         RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
837     }
838     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
839 
840     return NO_ERROR;
841 }
842 
getSupportedLayerGenericMetadata() const843 const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
844     return mSupportedLayerGenericMetadata;
845 }
846 
dump(std::string & result) const847 void HWComposer::dump(std::string& result) const {
848     result.append(mComposer->dumpDebugInfo());
849 }
850 
toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const851 std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
852         hal::HWDisplayId hwcDisplayId) const {
853     if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
854         it != mPhysicalDisplayIdMap.end()) {
855         return it->second;
856     }
857     return {};
858 }
859 
fromPhysicalDisplayId(PhysicalDisplayId displayId) const860 std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
861         PhysicalDisplayId displayId) const {
862     if (const auto it = mDisplayData.find(displayId);
863         it != mDisplayData.end() && !it->second.isVirtual) {
864         return it->second.hwcDisplay->getId();
865     }
866     return {};
867 }
868 
shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,bool hasDisplayIdentificationData) const869 bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
870                                             bool hasDisplayIdentificationData) const {
871     if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
872         ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
873               hwcDisplayId);
874         return true;
875     }
876 
877     if (!mHasMultiDisplaySupport && mInternalHwcDisplayId && mExternalHwcDisplayId) {
878         ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
879         return true;
880     }
881 
882     return false;
883 }
884 
onHotplugConnect(hal::HWDisplayId hwcDisplayId)885 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
886         hal::HWDisplayId hwcDisplayId) {
887     std::optional<DisplayIdentificationInfo> info;
888     if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
889         info = DisplayIdentificationInfo{.id = *displayId,
890                                          .name = std::string(),
891                                          .deviceProductInfo = std::nullopt};
892         if (mUpdateDeviceProductInfoOnHotplugReconnect) {
893             uint8_t port;
894             DisplayIdentificationData data;
895             getDisplayIdentificationData(hwcDisplayId, &port, &data);
896             if (auto newInfo = parseDisplayIdentificationData(port, data)) {
897                 info->deviceProductInfo = std::move(newInfo->deviceProductInfo);
898             } else {
899                 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
900             }
901         }
902     } else {
903         uint8_t port;
904         DisplayIdentificationData data;
905         const bool hasDisplayIdentificationData =
906                 getDisplayIdentificationData(hwcDisplayId, &port, &data);
907         if (mPhysicalDisplayIdMap.empty()) {
908             mHasMultiDisplaySupport = hasDisplayIdentificationData;
909             ALOGI("Switching to %s multi-display mode",
910                   mHasMultiDisplaySupport ? "generalized" : "legacy");
911         }
912 
913         if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
914             return {};
915         }
916 
917         info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
918             const bool isPrimary = !mInternalHwcDisplayId;
919             if (mHasMultiDisplaySupport) {
920                 if (const auto info = parseDisplayIdentificationData(port, data)) {
921                     return *info;
922                 }
923                 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
924             } else {
925                 ALOGW_IF(hasDisplayIdentificationData,
926                          "Ignoring identification data for display %" PRIu64, hwcDisplayId);
927                 port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
928             }
929 
930             return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
931                                              .name = isPrimary ? "Internal display"
932                                                                : "External display",
933                                              .deviceProductInfo = std::nullopt};
934         }();
935     }
936 
937     if (!isConnected(info->id)) {
938         allocatePhysicalDisplay(hwcDisplayId, info->id);
939     }
940     return info;
941 }
942 
onHotplugDisconnect(hal::HWDisplayId hwcDisplayId)943 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
944         hal::HWDisplayId hwcDisplayId) {
945     const auto displayId = toPhysicalDisplayId(hwcDisplayId);
946     if (!displayId) {
947         ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
948         return {};
949     }
950 
951     // The display will later be destroyed by a call to
952     // destroyDisplay(). For now we just mark it disconnected.
953     if (isConnected(*displayId)) {
954         mDisplayData[*displayId].hwcDisplay->setConnected(false);
955     } else {
956         ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
957     }
958     // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
959     // via SurfaceFlinger's onHotplugReceived callback handling
960     return DisplayIdentificationInfo{.id = *displayId,
961                                      .name = std::string(),
962                                      .deviceProductInfo = std::nullopt};
963 }
964 
loadCapabilities()965 void HWComposer::loadCapabilities() {
966     static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
967     auto capabilities = mComposer->getCapabilities();
968     for (auto capability : capabilities) {
969         mCapabilities.emplace(static_cast<hal::Capability>(capability));
970     }
971 }
972 
loadLayerMetadataSupport()973 void HWComposer::loadLayerMetadataSupport() {
974     mSupportedLayerGenericMetadata.clear();
975 
976     std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo;
977     const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo);
978     if (error != hardware::graphics::composer::V2_4::Error::NONE) {
979         if (error != hardware::graphics::composer::V2_4::Error::UNSUPPORTED) {
980             ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
981                   toString(error).c_str(), static_cast<int32_t>(error));
982         }
983         return;
984     }
985 
986     for (const auto& [name, mandatory] : supportedMetadataKeyInfo) {
987         mSupportedLayerGenericMetadata.emplace(name, mandatory);
988     }
989 }
990 
991 } // namespace impl
992 } // namespace android
993 
994 // TODO(b/129481165): remove the #pragma below and fix conversion issues
995 #pragma clang diagnostic pop // ignored "-Wconversion"
996