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