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 #include <chrono>
19 #pragma clang diagnostic push
20 #pragma clang diagnostic ignored "-Wconversion"
21
22 // #define LOG_NDEBUG 0
23
24 #undef LOG_TAG
25 #define LOG_TAG "HWComposer"
26 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
27
28 #include "HWComposer.h"
29
30 #include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
31 #include <android-base/properties.h>
32 #include <common/trace.h>
33 #include <compositionengine/Output.h>
34 #include <compositionengine/OutputLayer.h>
35 #include <compositionengine/impl/OutputLayerCompositionState.h>
36 #include <ftl/concat.h>
37 #include <log/log.h>
38 #include <ui/DebugUtils.h>
39 #include <ui/GraphicBuffer.h>
40 #include <utils/Errors.h>
41
42 #include "../Layer.h" // needed only for debugging
43 #include "../SurfaceFlingerProperties.h"
44 #include "ComposerHal.h"
45 #include "HWC2.h"
46
47 #define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
48 ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
49
50 #define LOG_DISPLAY_ERROR(displayId, msg) \
51 ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg)
52
53 #define LOG_HWC_ERROR(what, error, displayId) \
54 ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \
55 to_string(displayId).c_str(), to_string(error).c_str(), static_cast<int32_t>(error))
56
57 #define RETURN_IF_INVALID_DISPLAY(displayId, ...) \
58 do { \
59 if (mDisplayData.count(displayId) == 0) { \
60 LOG_DISPLAY_ERROR(displayId, "Invalid display"); \
61 return __VA_ARGS__; \
62 } \
63 } while (false)
64
65 #define RETURN_IF_HWC_ERROR_FOR(what, error, displayId, ...) \
66 do { \
67 if (error != hal::Error::NONE) { \
68 LOG_HWC_ERROR(what, error, displayId); \
69 return __VA_ARGS__; \
70 } \
71 } while (false)
72
73 #define RETURN_IF_HWC_ERROR(error, displayId, ...) \
74 RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)
75
76 using aidl::android::hardware::graphics::common::HdrConversionCapability;
77 using aidl::android::hardware::graphics::common::HdrConversionStrategy;
78 using aidl::android::hardware::graphics::composer3::Capability;
79 using aidl::android::hardware::graphics::composer3::DisplayCapability;
80 using aidl::android::hardware::graphics::composer3::DisplayConfiguration;
81 using namespace std::string_literals;
82
83 namespace android {
84
85 HWComposer::~HWComposer() = default;
86
87 namespace impl {
88
HWComposer(std::unique_ptr<Hwc2::Composer> composer)89 HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
90 : mComposer(std::move(composer)),
91 mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))),
92 mUpdateDeviceProductInfoOnHotplugReconnect(
93 sysprop::update_device_product_info_on_hotplug_reconnect(false)),
94 mEnableVrrTimeout(base::GetBoolProperty("debug.sf.vrr_timeout_hint_enabled"s, true)) {}
95
HWComposer(const std::string & composerServiceName)96 HWComposer::HWComposer(const std::string& composerServiceName)
97 : HWComposer(Hwc2::Composer::create(composerServiceName)) {}
98
~HWComposer()99 HWComposer::~HWComposer() {
100 mDisplayData.clear();
101 }
102
setCallback(HWC2::ComposerCallback & callback)103 void HWComposer::setCallback(HWC2::ComposerCallback& callback) {
104 loadCapabilities();
105 loadLayerMetadataSupport();
106 loadOverlayProperties();
107 loadHdrConversionCapabilities();
108
109 if (mRegisteredCallback) {
110 ALOGW("Callback already registered. Ignored extra registration attempt.");
111 return;
112 }
113 mRegisteredCallback = true;
114
115 mComposer->registerCallback(callback);
116 }
117
getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId,uint8_t * outPort,DisplayIdentificationData * outData) const118 bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
119 DisplayIdentificationData* outData) const {
120 const auto error = static_cast<hal::Error>(
121 mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
122 if (error != hal::Error::NONE) {
123 if (error != hal::Error::UNSUPPORTED) {
124 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
125 }
126 return false;
127 }
128 return true;
129 }
130
hasCapability(Capability capability) const131 bool HWComposer::hasCapability(Capability capability) const {
132 return mCapabilities.count(capability) > 0;
133 }
134
hasDisplayCapability(HalDisplayId displayId,DisplayCapability capability) const135 bool HWComposer::hasDisplayCapability(HalDisplayId displayId, DisplayCapability capability) const {
136 RETURN_IF_INVALID_DISPLAY(displayId, false);
137 return mDisplayData.at(displayId).hwcDisplay->hasCapability(capability);
138 }
139
onHotplug(hal::HWDisplayId hwcDisplayId,hal::Connection connection)140 std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
141 hal::Connection connection) {
142 switch (connection) {
143 case hal::Connection::CONNECTED:
144 return onHotplugConnect(hwcDisplayId);
145 case hal::Connection::DISCONNECTED:
146 return onHotplugDisconnect(hwcDisplayId);
147 case hal::Connection::INVALID:
148 return {};
149 }
150 }
151
updatesDeviceProductInfoOnHotplugReconnect() const152 bool HWComposer::updatesDeviceProductInfoOnHotplugReconnect() const {
153 return mUpdateDeviceProductInfoOnHotplugReconnect;
154 }
155
onVsync(hal::HWDisplayId hwcDisplayId,nsecs_t timestamp)156 std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId,
157 nsecs_t timestamp) {
158 const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId);
159 if (!displayIdOpt) {
160 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
161 return {};
162 }
163
164 RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {});
165
166 auto& displayData = mDisplayData[*displayIdOpt];
167
168 {
169 // There have been reports of HWCs that signal several vsync events
170 // with the same timestamp when turning the display off and on. This
171 // is a bug in the HWC implementation, but filter the extra events
172 // out here so they don't cause havoc downstream.
173 if (timestamp == displayData.lastPresentTimestamp) {
174 ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
175 to_string(*displayIdOpt).c_str(), timestamp);
176 return {};
177 }
178
179 displayData.lastPresentTimestamp = timestamp;
180 }
181
182 SFTRACE_INT(ftl::Concat("HW_VSYNC_", displayIdOpt->value).c_str(),
183 displayData.vsyncTraceToggle);
184 displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
185
186 return displayIdOpt;
187 }
188
getMaxVirtualDisplayCount() const189 size_t HWComposer::getMaxVirtualDisplayCount() const {
190 return mComposer->getMaxVirtualDisplayCount();
191 }
192
getMaxVirtualDisplayDimension() const193 size_t HWComposer::getMaxVirtualDisplayDimension() const {
194 return mMaxVirtualDisplayDimension;
195 }
196
allocateVirtualDisplay(HalVirtualDisplayId displayId,ui::Size resolution,ui::PixelFormat * format)197 bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size resolution,
198 ui::PixelFormat* format) {
199 if (!resolution.isValid()) {
200 ALOGE("%s: Invalid resolution %dx%d", __func__, resolution.width, resolution.height);
201 return false;
202 }
203
204 const uint32_t width = static_cast<uint32_t>(resolution.width);
205 const uint32_t height = static_cast<uint32_t>(resolution.height);
206
207 if (mMaxVirtualDisplayDimension > 0 &&
208 (width > mMaxVirtualDisplayDimension || height > mMaxVirtualDisplayDimension)) {
209 ALOGE("%s: Resolution %ux%u exceeds maximum dimension %zu", __func__, width, height,
210 mMaxVirtualDisplayDimension);
211 return false;
212 }
213
214 hal::HWDisplayId hwcDisplayId;
215 const auto error = static_cast<hal::Error>(
216 mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
217 RETURN_IF_HWC_ERROR_FOR("createVirtualDisplay", error, displayId, false);
218
219 auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
220 hwcDisplayId, hal::DisplayType::VIRTUAL);
221 display->setConnected(true);
222 auto& displayData = mDisplayData[displayId];
223 displayData.hwcDisplay = std::move(display);
224 return true;
225 }
226
allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,PhysicalDisplayId displayId,std::optional<ui::Size> physicalSize)227 void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, PhysicalDisplayId displayId,
228 std::optional<ui::Size> physicalSize) {
229 mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
230
231 if (!mPrimaryHwcDisplayId) {
232 mPrimaryHwcDisplayId = hwcDisplayId;
233 }
234
235 auto& displayData = mDisplayData[displayId];
236 auto newDisplay =
237 std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
238 hal::DisplayType::PHYSICAL);
239 newDisplay->setConnected(true);
240 newDisplay->setPhysicalSizeInMm(physicalSize);
241 displayData.hwcDisplay = std::move(newDisplay);
242 }
243
getAttribute(hal::HWDisplayId hwcDisplayId,hal::HWConfigId configId,hal::Attribute attribute) const244 int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
245 hal::Attribute attribute) const {
246 int32_t value = 0;
247 auto error = static_cast<hal::Error>(
248 mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
249
250 RETURN_IF_HWC_ERROR_FOR("getDisplayAttribute", error, *toPhysicalDisplayId(hwcDisplayId), -1);
251 return value;
252 }
253
createLayer(HalDisplayId displayId)254 std::shared_ptr<HWC2::Layer> HWComposer::createLayer(HalDisplayId displayId) {
255 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
256
257 auto expected = mDisplayData[displayId].hwcDisplay->createLayer();
258 if (!expected.has_value()) {
259 auto error = std::move(expected).error();
260 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
261 }
262 return std::move(expected).value();
263 }
264
isConnected(PhysicalDisplayId displayId) const265 bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
266 return mDisplayData.count(displayId) && mDisplayData.at(displayId).hwcDisplay->isConnected();
267 }
268
getModes(PhysicalDisplayId displayId,int32_t maxFrameIntervalNs) const269 std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId,
270 int32_t maxFrameIntervalNs) const {
271 RETURN_IF_INVALID_DISPLAY(displayId, {});
272
273 const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
274
275 if (mComposer->isVrrSupported()) {
276 return getModesFromDisplayConfigurations(hwcDisplayId, maxFrameIntervalNs);
277 }
278
279 return getModesFromLegacyDisplayConfigs(hwcDisplayId);
280 }
281
getEstimatedDotsPerInchFromSize(uint64_t hwcDisplayId,const HWCDisplayMode & hwcMode) const282 DisplayConfiguration::Dpi HWComposer::getEstimatedDotsPerInchFromSize(
283 uint64_t hwcDisplayId, const HWCDisplayMode& hwcMode) const {
284 if (!FlagManager::getInstance().correct_dpi_with_display_size()) {
285 return {-1, -1};
286 }
287 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
288 if (const auto it = mDisplayData.find(displayId.value());
289 it != mDisplayData.end() && it->second.hwcDisplay->getPhysicalSizeInMm()) {
290 ui::Size size = it->second.hwcDisplay->getPhysicalSizeInMm().value();
291 if (hwcMode.width > 0 && hwcMode.height > 0 && size.width > 0 && size.height > 0) {
292 static constexpr float kMmPerInch = 25.4f;
293 return {hwcMode.width * kMmPerInch / size.width,
294 hwcMode.height * kMmPerInch / size.height};
295 }
296 }
297 }
298 return {-1, -1};
299 }
300
correctedDpiIfneeded(DisplayConfiguration::Dpi dpi,DisplayConfiguration::Dpi estimatedDpi) const301 DisplayConfiguration::Dpi HWComposer::correctedDpiIfneeded(
302 DisplayConfiguration::Dpi dpi, DisplayConfiguration::Dpi estimatedDpi) const {
303 // hwc can be unreliable when it comes to dpi. A rough estimated dpi may yield better
304 // results. For instance, libdrm and bad edid may result in a dpi of {350, 290} for a
305 // 16:9 3840x2160 display, which would match a 4:3 aspect ratio.
306 // The logic here checks if hwc was able to provide some dpi, and if so if the dpi
307 // disparity between the axes is more reasonable than a rough estimate, otherwise use
308 // the estimated dpi as a corrected value.
309 if (estimatedDpi.x == -1 || estimatedDpi.y == -1) {
310 return dpi;
311 }
312 if (dpi.x == -1 || dpi.y == -1) {
313 return estimatedDpi;
314 }
315 if (std::min(dpi.x, dpi.y) != 0 && std::min(estimatedDpi.x, estimatedDpi.y) != 0 &&
316 abs(dpi.x - dpi.y) / std::min(dpi.x, dpi.y) >
317 abs(estimatedDpi.x - estimatedDpi.y) / std::min(estimatedDpi.x, estimatedDpi.y)) {
318 return estimatedDpi;
319 }
320 return dpi;
321 }
322
getModesFromDisplayConfigurations(uint64_t hwcDisplayId,int32_t maxFrameIntervalNs) const323 std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromDisplayConfigurations(
324 uint64_t hwcDisplayId, int32_t maxFrameIntervalNs) const {
325 std::vector<hal::DisplayConfiguration> configs;
326 auto error = static_cast<hal::Error>(
327 mComposer->getDisplayConfigurations(hwcDisplayId, maxFrameIntervalNs, &configs));
328 RETURN_IF_HWC_ERROR_FOR("getDisplayConfigurations", error, *toPhysicalDisplayId(hwcDisplayId),
329 {});
330
331 std::vector<HWCDisplayMode> modes;
332 modes.reserve(configs.size());
333 for (auto config : configs) {
334 auto hwcMode = HWCDisplayMode{.hwcId = static_cast<hal::HWConfigId>(config.configId),
335 .width = config.width,
336 .height = config.height,
337 .vsyncPeriod = config.vsyncPeriod,
338 .configGroup = config.configGroup,
339 .vrrConfig = config.vrrConfig,
340 .hdrOutputType = config.hdrOutputType};
341
342 const DisplayConfiguration::Dpi estimatedDPI =
343 getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
344 if (config.dpi) {
345 const DisplayConfiguration::Dpi dpi =
346 correctedDpiIfneeded(config.dpi.value(), estimatedDPI);
347 hwcMode.dpiX = dpi.x;
348 hwcMode.dpiY = dpi.y;
349 } else if (estimatedDPI.x != -1 && estimatedDPI.y != -1) {
350 hwcMode.dpiX = estimatedDPI.x;
351 hwcMode.dpiY = estimatedDPI.y;
352 }
353
354 if (!mEnableVrrTimeout) {
355 hwcMode.vrrConfig->notifyExpectedPresentConfig = {};
356 }
357
358 modes.push_back(hwcMode);
359 }
360
361 return modes;
362 }
363
getModesFromLegacyDisplayConfigs(uint64_t hwcDisplayId) const364 std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromLegacyDisplayConfigs(
365 uint64_t hwcDisplayId) const {
366 std::vector<hal::HWConfigId> configIds;
367 auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
368 RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
369
370 std::vector<HWCDisplayMode> modes;
371 modes.reserve(configIds.size());
372 for (auto configId : configIds) {
373 auto hwcMode = HWCDisplayMode{
374 .hwcId = configId,
375 .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
376 .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
377 .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
378 .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
379 };
380
381 const int32_t dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X);
382 const int32_t dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y);
383 const DisplayConfiguration::Dpi hwcDpi =
384 DisplayConfiguration::Dpi{dpiX == -1 ? dpiX : dpiX / 1000.f,
385 dpiY == -1 ? dpiY : dpiY / 1000.f};
386 const DisplayConfiguration::Dpi estimatedDPI =
387 getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
388 const DisplayConfiguration::Dpi dpi = correctedDpiIfneeded(hwcDpi, estimatedDPI);
389 hwcMode.dpiX = dpi.x;
390 hwcMode.dpiY = dpi.y;
391
392 modes.push_back(hwcMode);
393 }
394 return modes;
395 }
396
getActiveMode(PhysicalDisplayId displayId) const397 ftl::Expected<hal::HWConfigId, status_t> HWComposer::getActiveMode(
398 PhysicalDisplayId displayId) const {
399 RETURN_IF_INVALID_DISPLAY(displayId, ftl::Unexpected(BAD_INDEX));
400 const auto hwcId = *fromPhysicalDisplayId(displayId);
401
402 hal::HWConfigId configId;
403 const auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
404 if (error == hal::Error::BAD_CONFIG) {
405 return ftl::Unexpected(NO_INIT);
406 }
407
408 RETURN_IF_HWC_ERROR_FOR("getActiveConfig", error, displayId, ftl::Unexpected(UNKNOWN_ERROR));
409 return configId;
410 }
411
412 // Composer 2.4
413
getDisplayConnectionType(PhysicalDisplayId displayId) const414 ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
415 RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal);
416 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
417
418 if (const auto connectionType = hwcDisplay->getConnectionType()) {
419 return connectionType.value();
420 } else {
421 LOG_HWC_ERROR(__func__, connectionType.error(), displayId);
422 return hwcDisplay->getId() == mPrimaryHwcDisplayId ? ui::DisplayConnectionType::Internal
423 : ui::DisplayConnectionType::External;
424 }
425 }
426
isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const427 bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const {
428 RETURN_IF_INVALID_DISPLAY(displayId, false);
429 return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
430 }
431
getDisplayVsyncPeriod(PhysicalDisplayId displayId) const432 ftl::Expected<nsecs_t, status_t> HWComposer::getDisplayVsyncPeriod(
433 PhysicalDisplayId displayId) const {
434 RETURN_IF_INVALID_DISPLAY(displayId, ftl::Unexpected(BAD_INDEX));
435
436 if (!isVsyncPeriodSwitchSupported(displayId)) {
437 return ftl::Unexpected(INVALID_OPERATION);
438 }
439
440 const auto hwcId = *fromPhysicalDisplayId(displayId);
441 Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
442 const auto error =
443 static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
444 RETURN_IF_HWC_ERROR(error, displayId, ftl::Unexpected(UNKNOWN_ERROR));
445 return static_cast<nsecs_t>(vsyncPeriodNanos);
446 }
447
getColorModes(PhysicalDisplayId displayId) const448 std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
449 RETURN_IF_INVALID_DISPLAY(displayId, {});
450
451 std::vector<ui::ColorMode> modes;
452 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
453 RETURN_IF_HWC_ERROR(error, displayId, {});
454 return modes;
455 }
456
setActiveColorMode(PhysicalDisplayId displayId,ui::ColorMode mode,ui::RenderIntent renderIntent)457 status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode,
458 ui::RenderIntent renderIntent) {
459 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
460
461 auto& displayData = mDisplayData[displayId];
462 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
463 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
464 decodeRenderIntent(renderIntent) + ")")
465 .c_str(),
466 error, displayId, UNKNOWN_ERROR);
467
468 return NO_ERROR;
469 }
470
setVsyncEnabled(PhysicalDisplayId displayId,hal::Vsync enabled)471 void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) {
472 RETURN_IF_INVALID_DISPLAY(displayId);
473 auto& displayData = mDisplayData[displayId];
474
475 // NOTE: we use our own internal lock here because we have to call
476 // into the HWC with the lock held, and we want to make sure
477 // that even if HWC blocks (which it shouldn't), it won't
478 // affect other threads.
479 std::lock_guard lock(displayData.vsyncEnabledLock);
480 if (enabled == displayData.vsyncEnabled) {
481 return;
482 }
483
484 SFTRACE_CALL();
485 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
486 RETURN_IF_HWC_ERROR(error, displayId);
487
488 displayData.vsyncEnabled = enabled;
489
490 SFTRACE_INT(ftl::Concat("HW_VSYNC_ON_", displayId.value).c_str(),
491 enabled == hal::Vsync::ENABLE ? 1 : 0);
492 }
493
setClientTarget(HalDisplayId displayId,uint32_t slot,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & target,ui::Dataspace dataspace,float hdrSdrRatio)494 status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot,
495 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
496 ui::Dataspace dataspace, float hdrSdrRatio) {
497 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
498
499 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
500 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
501 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace, hdrSdrRatio);
502 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
503 return NO_ERROR;
504 }
505
getDeviceCompositionChanges(HalDisplayId displayId,bool frameUsesClientComposition,std::optional<std::chrono::steady_clock::time_point> earliestPresentTime,nsecs_t expectedPresentTime,Fps frameInterval,std::optional<android::HWComposer::DeviceRequestedChanges> * outChanges)506 status_t HWComposer::getDeviceCompositionChanges(
507 HalDisplayId displayId, bool frameUsesClientComposition,
508 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime,
509 nsecs_t expectedPresentTime, Fps frameInterval,
510 std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
511 SFTRACE_CALL();
512
513 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
514
515 auto& displayData = mDisplayData[displayId];
516 auto& hwcDisplay = displayData.hwcDisplay;
517 if (!hwcDisplay->isConnected()) {
518 return NO_ERROR;
519 }
520
521 uint32_t numTypes = 0;
522 uint32_t numRequests = 0;
523
524 hal::Error error = hal::Error::NONE;
525
526 // First try to skip validate altogether. We can do that when
527 // 1. The previous frame has not been presented yet or already passed the
528 // earliest time to present. Otherwise, we may present a frame too early.
529 // 2. There is no client composition. Otherwise, we first need to render the
530 // client target buffer.
531 const bool canSkipValidate = [&] {
532 // We must call validate if we have client composition
533 if (frameUsesClientComposition) {
534 return false;
535 }
536
537 // If composer supports getting the expected present time, we can skip
538 // as composer will make sure to prevent early presentation
539 if (!earliestPresentTime) {
540 return true;
541 }
542
543 // composer doesn't support getting the expected present time. We can only
544 // skip validate if we know that we are not going to present early.
545 return std::chrono::steady_clock::now() >= *earliestPresentTime;
546 }();
547
548 displayData.validateWasSkipped = false;
549 SFTRACE_FORMAT("NextFrameInterval %d_Hz", frameInterval.getIntValue());
550 if (canSkipValidate) {
551 sp<Fence> outPresentFence = Fence::NO_FENCE;
552 uint32_t state = UINT32_MAX;
553 error = hwcDisplay->presentOrValidate(expectedPresentTime, frameInterval.getPeriodNsecs(),
554 &numTypes, &numRequests, &outPresentFence, &state);
555 if (!hasChangesError(error)) {
556 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
557 }
558 if (state == 1) { //Present Succeeded.
559 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
560 error = hwcDisplay->getReleaseFences(&releaseFences);
561 displayData.releaseFences = std::move(releaseFences);
562 displayData.lastPresentFence = outPresentFence;
563 displayData.validateWasSkipped = true;
564 displayData.presentError = error;
565 return NO_ERROR;
566 }
567 // Present failed but Validate ran.
568 } else {
569 error = hwcDisplay->validate(expectedPresentTime, frameInterval.getPeriodNsecs(), &numTypes,
570 &numRequests);
571 }
572 ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
573 if (!hasChangesError(error)) {
574 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
575 }
576
577 android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
578 changedTypes.reserve(numTypes);
579 error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
580 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
581
582 auto displayRequests = static_cast<hal::DisplayRequest>(0);
583 android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
584 layerRequests.reserve(numRequests);
585 error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
586 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
587
588 DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
589 error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
590 RETURN_IF_HWC_ERROR_FOR("getClientTargetProperty", error, displayId, BAD_INDEX);
591
592 DeviceRequestedChanges::LayerLuts layerLuts;
593 error = hwcDisplay->getRequestedLuts(&layerLuts, mLutFileDescriptorMapper);
594 RETURN_IF_HWC_ERROR_FOR("getRequestedLuts", error, displayId, BAD_INDEX);
595
596 outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
597 std::move(layerRequests),
598 std::move(clientTargetProperty),
599 std::move(layerLuts)});
600 error = hwcDisplay->acceptChanges();
601 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
602
603 return NO_ERROR;
604 }
605
getPresentFence(HalDisplayId displayId) const606 sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const {
607 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
608 return mDisplayData.at(displayId).lastPresentFence;
609 }
610
getPresentTimestamp(PhysicalDisplayId displayId) const611 nsecs_t HWComposer::getPresentTimestamp(PhysicalDisplayId displayId) const {
612 RETURN_IF_INVALID_DISPLAY(displayId, 0);
613 return mDisplayData.at(displayId).lastPresentTimestamp;
614 }
615
getLayerReleaseFence(HalDisplayId displayId,HWC2::Layer * layer) const616 sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
617 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
618 const auto& displayFences = mDisplayData.at(displayId).releaseFences;
619 auto fence = displayFences.find(layer);
620 if (fence == displayFences.end()) {
621 ALOGV("getLayerReleaseFence: Release fence not found");
622 return Fence::NO_FENCE;
623 }
624 return fence->second;
625 }
626
presentAndGetReleaseFences(HalDisplayId displayId,std::optional<std::chrono::steady_clock::time_point> earliestPresentTime)627 status_t HWComposer::presentAndGetReleaseFences(
628 HalDisplayId displayId,
629 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) {
630 SFTRACE_CALL();
631
632 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
633
634 auto& displayData = mDisplayData[displayId];
635 auto& hwcDisplay = displayData.hwcDisplay;
636
637 if (displayData.validateWasSkipped) {
638 // explicitly flush all pending commands
639 auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
640 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
641 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
642 return NO_ERROR;
643 }
644
645 if (earliestPresentTime) {
646 SFTRACE_NAME("wait for earliest present time");
647 std::this_thread::sleep_until(*earliestPresentTime);
648 }
649
650 auto error = hwcDisplay->present(&displayData.lastPresentFence);
651 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
652
653 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
654 error = hwcDisplay->getReleaseFences(&releaseFences);
655 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
656
657 displayData.releaseFences = std::move(releaseFences);
658
659 return NO_ERROR;
660 }
661
executeCommands(HalDisplayId displayId)662 status_t HWComposer::executeCommands(HalDisplayId displayId) {
663 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
664 auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
665 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
666 return NO_ERROR;
667 }
668
setPowerMode(PhysicalDisplayId displayId,hal::PowerMode mode)669 status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
670 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
671
672 if (mode == hal::PowerMode::OFF) {
673 setVsyncEnabled(displayId, hal::Vsync::DISABLE);
674 }
675
676 const auto& displayData = mDisplayData[displayId];
677 auto& hwcDisplay = displayData.hwcDisplay;
678 switch (mode) {
679 case hal::PowerMode::OFF:
680 case hal::PowerMode::ON:
681 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
682 {
683 auto error = hwcDisplay->setPowerMode(mode);
684 if (error != hal::Error::NONE) {
685 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
686 displayId);
687 }
688 }
689 break;
690 case hal::PowerMode::DOZE:
691 case hal::PowerMode::DOZE_SUSPEND:
692 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
693 {
694 bool supportsDoze = false;
695 const auto queryDozeError = hwcDisplay->supportsDoze(&supportsDoze);
696
697 // queryDozeError might be NO_RESOURCES, in the case of a display that has never
698 // been turned on. In that case, attempt to set to DOZE anyway.
699 if (!supportsDoze && queryDozeError == hal::Error::NONE) {
700 mode = hal::PowerMode::ON;
701 }
702
703 auto error = hwcDisplay->setPowerMode(mode);
704 if (error != hal::Error::NONE) {
705 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
706 displayId);
707 // If the display had never been turned on, so its doze
708 // support was unknown, it may truly not support doze. Try
709 // switching it to ON instead.
710 if (queryDozeError == hal::Error::NO_RESOURCES) {
711 ALOGD("%s: failed to set %s to %s. Trying again with ON", __func__,
712 to_string(displayId).c_str(), to_string(mode).c_str());
713 error = hwcDisplay->setPowerMode(hal::PowerMode::ON);
714 if (error != hal::Error::NONE) {
715 LOG_HWC_ERROR("setPowerMode(ON)", error, displayId);
716 }
717 }
718 }
719 }
720 break;
721 default:
722 ALOGV("setPowerMode: Not calling HWC");
723 break;
724 }
725
726 return NO_ERROR;
727 }
728
setActiveModeWithConstraints(PhysicalDisplayId displayId,hal::HWConfigId hwcModeId,const hal::VsyncPeriodChangeConstraints & constraints,hal::VsyncPeriodChangeTimeline * outTimeline)729 status_t HWComposer::setActiveModeWithConstraints(
730 PhysicalDisplayId displayId, hal::HWConfigId hwcModeId,
731 const hal::VsyncPeriodChangeConstraints& constraints,
732 hal::VsyncPeriodChangeTimeline* outTimeline) {
733 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
734
735 auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
736 constraints,
737 outTimeline);
738 if (error == hal::Error::CONFIG_FAILED) {
739 RETURN_IF_HWC_ERROR_FOR("setActiveConfigWithConstraints", error, displayId,
740 FAILED_TRANSACTION);
741 }
742 RETURN_IF_HWC_ERROR_FOR("setActiveConfigWithConstraints", error, displayId, UNKNOWN_ERROR);
743 return NO_ERROR;
744 }
745
setColorTransform(HalDisplayId displayId,const mat4 & transform)746 status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) {
747 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
748
749 auto& displayData = mDisplayData[displayId];
750 auto error = displayData.hwcDisplay->setColorTransform(transform);
751 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
752 return NO_ERROR;
753 }
754
disconnectDisplay(HalDisplayId displayId)755 void HWComposer::disconnectDisplay(HalDisplayId displayId) {
756 RETURN_IF_INVALID_DISPLAY(displayId);
757 auto& displayData = mDisplayData[displayId];
758 const auto hwcDisplayId = displayData.hwcDisplay->getId();
759
760 mPhysicalDisplayIdMap.erase(hwcDisplayId);
761 mDisplayData.erase(displayId);
762
763 // Reset the primary display ID if we're disconnecting it.
764 // This way isHeadless() will return false, which is necessary
765 // because getPrimaryDisplayId() will crash.
766 if (mPrimaryHwcDisplayId == hwcDisplayId) {
767 mPrimaryHwcDisplayId.reset();
768 }
769 }
770
setOutputBuffer(HalVirtualDisplayId displayId,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & buffer)771 status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
772 const sp<GraphicBuffer>& buffer) {
773 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
774 const auto& displayData = mDisplayData[displayId];
775
776 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
777 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
778 return NO_ERROR;
779 }
780
clearReleaseFences(HalDisplayId displayId)781 void HWComposer::clearReleaseFences(HalDisplayId displayId) {
782 RETURN_IF_INVALID_DISPLAY(displayId);
783 mDisplayData[displayId].releaseFences.clear();
784 }
785
getHdrCapabilities(HalDisplayId displayId,HdrCapabilities * outCapabilities)786 status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) {
787 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
788
789 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
790 auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
791 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
792 return NO_ERROR;
793 }
794
795 const aidl::android::hardware::graphics::composer3::OverlayProperties&
getOverlaySupport() const796 HWComposer::getOverlaySupport() const {
797 return mOverlayProperties;
798 }
799
getSupportedPerFrameMetadata(HalDisplayId displayId) const800 int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const {
801 RETURN_IF_INVALID_DISPLAY(displayId, 0);
802 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
803 }
804
getRenderIntents(HalDisplayId displayId,ui::ColorMode colorMode) const805 std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId,
806 ui::ColorMode colorMode) const {
807 RETURN_IF_INVALID_DISPLAY(displayId, {});
808
809 std::vector<ui::RenderIntent> renderIntents;
810 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
811 RETURN_IF_HWC_ERROR(error, displayId, {});
812 return renderIntents;
813 }
814
getDataspaceSaturationMatrix(HalDisplayId displayId,ui::Dataspace dataspace)815 mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) {
816 RETURN_IF_INVALID_DISPLAY(displayId, {});
817
818 mat4 matrix;
819 auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
820 &matrix);
821 RETURN_IF_HWC_ERROR(error, displayId, {});
822 return matrix;
823 }
824
getDisplayedContentSamplingAttributes(HalDisplayId displayId,ui::PixelFormat * outFormat,ui::Dataspace * outDataspace,uint8_t * outComponentMask)825 status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId,
826 ui::PixelFormat* outFormat,
827 ui::Dataspace* outDataspace,
828 uint8_t* outComponentMask) {
829 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
830 const auto error =
831 mDisplayData[displayId]
832 .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
833 outComponentMask);
834 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
835 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
836 return NO_ERROR;
837 }
838
setDisplayContentSamplingEnabled(HalDisplayId displayId,bool enabled,uint8_t componentMask,uint64_t maxFrames)839 status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled,
840 uint8_t componentMask, uint64_t maxFrames) {
841 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
842 const auto error =
843 mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
844 componentMask,
845 maxFrames);
846
847 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
848 if (error == hal::Error::BAD_PARAMETER) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
849 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
850 return NO_ERROR;
851 }
852
getDisplayedContentSample(HalDisplayId displayId,uint64_t maxFrames,uint64_t timestamp,DisplayedFrameStats * outStats)853 status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames,
854 uint64_t timestamp, DisplayedFrameStats* outStats) {
855 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
856 const auto error =
857 mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
858 outStats);
859 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
860 return NO_ERROR;
861 }
862
setDisplayBrightness(PhysicalDisplayId displayId,float brightness,float brightnessNits,const Hwc2::Composer::DisplayBrightnessOptions & options)863 ftl::Future<status_t> HWComposer::setDisplayBrightness(
864 PhysicalDisplayId displayId, float brightness, float brightnessNits,
865 const Hwc2::Composer::DisplayBrightnessOptions& options) {
866 RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX));
867 auto& display = mDisplayData[displayId].hwcDisplay;
868
869 return display->setDisplayBrightness(brightness, brightnessNits, options)
870 .then([displayId](hal::Error error) -> status_t {
871 if (error == hal::Error::UNSUPPORTED) {
872 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
873 }
874 if (error == hal::Error::BAD_PARAMETER) {
875 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
876 }
877 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
878 return NO_ERROR;
879 });
880 }
881
getValidateSkipped(HalDisplayId displayId) const882 bool HWComposer::getValidateSkipped(HalDisplayId displayId) const {
883 if (mDisplayData.count(displayId) == 0) {
884 return false;
885 }
886 return mDisplayData.at(displayId).validateWasSkipped;
887 }
888
setBootDisplayMode(PhysicalDisplayId displayId,hal::HWConfigId displayModeId)889 status_t HWComposer::setBootDisplayMode(PhysicalDisplayId displayId,
890 hal::HWConfigId displayModeId) {
891 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
892 const auto error = mDisplayData[displayId].hwcDisplay->setBootDisplayConfig(displayModeId);
893 if (error == hal::Error::UNSUPPORTED) {
894 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
895 }
896 if (error == hal::Error::BAD_PARAMETER) {
897 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
898 }
899 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
900 return NO_ERROR;
901 }
902
clearBootDisplayMode(PhysicalDisplayId displayId)903 status_t HWComposer::clearBootDisplayMode(PhysicalDisplayId displayId) {
904 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
905 const auto error = mDisplayData[displayId].hwcDisplay->clearBootDisplayConfig();
906 if (error == hal::Error::UNSUPPORTED) {
907 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
908 }
909 if (error == hal::Error::BAD_PARAMETER) {
910 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
911 }
912 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
913 return NO_ERROR;
914 }
915
getPreferredBootDisplayMode(PhysicalDisplayId displayId)916 std::optional<hal::HWConfigId> HWComposer::getPreferredBootDisplayMode(
917 PhysicalDisplayId displayId) {
918 RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
919 hal::HWConfigId displayModeId;
920 const auto error =
921 mDisplayData[displayId].hwcDisplay->getPreferredBootDisplayConfig(&displayModeId);
922 if (error != hal::Error::NONE) {
923 LOG_DISPLAY_ERROR(displayId, to_string(error).c_str());
924 return std::nullopt;
925 }
926 return displayModeId;
927 }
928
getHdrConversionCapabilities() const929 std::vector<HdrConversionCapability> HWComposer::getHdrConversionCapabilities() const {
930 return mHdrConversionCapabilities;
931 }
932
setHdrConversionStrategy(HdrConversionStrategy hdrConversionStrategy,aidl::android::hardware::graphics::common::Hdr * outPreferredHdrOutputType)933 status_t HWComposer::setHdrConversionStrategy(
934 HdrConversionStrategy hdrConversionStrategy,
935 aidl::android::hardware::graphics::common::Hdr* outPreferredHdrOutputType) {
936 const auto error =
937 mComposer->setHdrConversionStrategy(hdrConversionStrategy, outPreferredHdrOutputType);
938 if (error != hal::Error::NONE) {
939 ALOGE("Error in setting HDR conversion strategy %s", to_string(error).c_str());
940 return INVALID_OPERATION;
941 }
942 return NO_ERROR;
943 }
944
setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId displayId,bool enabled)945 status_t HWComposer::setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId displayId,
946 bool enabled) {
947 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
948 const auto error =
949 mComposer->setRefreshRateChangedCallbackDebugEnabled(mDisplayData[displayId]
950 .hwcDisplay->getId(),
951 enabled);
952 if (error != hal::Error::NONE) {
953 ALOGE("Error in setting refresh refresh rate change callback debug enabled %s",
954 to_string(error).c_str());
955 return INVALID_OPERATION;
956 }
957 return NO_ERROR;
958 }
959
notifyExpectedPresent(PhysicalDisplayId displayId,TimePoint expectedPresentTime,Fps frameInterval)960 status_t HWComposer::notifyExpectedPresent(PhysicalDisplayId displayId,
961 TimePoint expectedPresentTime, Fps frameInterval) {
962 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
963 SFTRACE_FORMAT("%s ExpectedPresentTime in %.2fms frameInterval %.2fms", __func__,
964 ticks<std::milli, float>(expectedPresentTime - TimePoint::now()),
965 ticks<std::milli, float>(Duration::fromNs(frameInterval.getPeriodNsecs())));
966 const auto error = mComposer->notifyExpectedPresent(mDisplayData[displayId].hwcDisplay->getId(),
967 expectedPresentTime.ns(),
968 frameInterval.getPeriodNsecs());
969 if (error != hal::Error::NONE) {
970 ALOGE("Error in notifyExpectedPresent call %s", to_string(error).c_str());
971 return INVALID_OPERATION;
972 }
973 return NO_ERROR;
974 }
975
getDisplayDecorationSupport(PhysicalDisplayId displayId,std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport> * support)976 status_t HWComposer::getDisplayDecorationSupport(
977 PhysicalDisplayId displayId,
978 std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
979 support) {
980 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
981 const auto error = mDisplayData[displayId].hwcDisplay->getDisplayDecorationSupport(support);
982 if (error == hal::Error::UNSUPPORTED) {
983 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
984 }
985 if (error == hal::Error::BAD_PARAMETER) {
986 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
987 }
988 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
989 return NO_ERROR;
990 }
991
setAutoLowLatencyMode(PhysicalDisplayId displayId,bool on)992 status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
993 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
994 const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
995 if (error == hal::Error::UNSUPPORTED) {
996 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
997 }
998 if (error == hal::Error::BAD_PARAMETER) {
999 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1000 }
1001 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1002 return NO_ERROR;
1003 }
1004
getSupportedContentTypes(PhysicalDisplayId displayId,std::vector<hal::ContentType> * outSupportedContentTypes) const1005 status_t HWComposer::getSupportedContentTypes(
1006 PhysicalDisplayId displayId,
1007 std::vector<hal::ContentType>* outSupportedContentTypes) const {
1008 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1009 const auto error = mDisplayData.at(displayId).hwcDisplay->getSupportedContentTypes(
1010 outSupportedContentTypes);
1011
1012 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1013
1014 return NO_ERROR;
1015 }
1016
setContentType(PhysicalDisplayId displayId,hal::ContentType contentType)1017 status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) {
1018 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1019 const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
1020 if (error == hal::Error::UNSUPPORTED) {
1021 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1022 }
1023 if (error == hal::Error::BAD_PARAMETER) {
1024 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1025 }
1026 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1027
1028 return NO_ERROR;
1029 }
1030
getMaxLayerPictureProfiles(PhysicalDisplayId displayId)1031 int32_t HWComposer::getMaxLayerPictureProfiles(PhysicalDisplayId displayId) {
1032 int32_t maxProfiles = 0;
1033 RETURN_IF_INVALID_DISPLAY(displayId, 0);
1034 const auto error = mDisplayData[displayId].hwcDisplay->getMaxLayerPictureProfiles(&maxProfiles);
1035 RETURN_IF_HWC_ERROR(error, displayId, 0);
1036 return maxProfiles;
1037 }
1038
setDisplayPictureProfileHandle(PhysicalDisplayId displayId,const PictureProfileHandle & handle)1039 status_t HWComposer::setDisplayPictureProfileHandle(PhysicalDisplayId displayId,
1040 const PictureProfileHandle& handle) {
1041 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1042 const auto error = mDisplayData[displayId].hwcDisplay->setPictureProfileHandle(handle);
1043 if (error != hal::Error::UNSUPPORTED) {
1044 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1045 }
1046 return NO_ERROR;
1047 }
1048
getSupportedLayerGenericMetadata() const1049 const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
1050 return mSupportedLayerGenericMetadata;
1051 }
1052
1053 ftl::SmallMap<HWC2::Layer*, ndk::ScopedFileDescriptor, 20>&
getLutFileDescriptorMapper()1054 HWComposer::getLutFileDescriptorMapper() {
1055 return mLutFileDescriptorMapper;
1056 }
1057
dumpOverlayProperties(std::string & result) const1058 void HWComposer::dumpOverlayProperties(std::string& result) const {
1059 // dump overlay properties
1060 result.append("OverlayProperties:\n");
1061 base::StringAppendF(&result, "supportMixedColorSpaces: %d\n",
1062 mOverlayProperties.supportMixedColorSpaces);
1063 base::StringAppendF(&result, "SupportedBufferCombinations(%zu entries)\n",
1064 mOverlayProperties.combinations.size());
1065 for (const auto& combination : mOverlayProperties.combinations) {
1066 result.append(" pixelFormats=\n");
1067 for (const auto& pixelFormat : combination.pixelFormats) {
1068 base::StringAppendF(&result, " %s (%d)\n",
1069 decodePixelFormat(static_cast<PixelFormat>(pixelFormat)).c_str(),
1070 static_cast<uint32_t>(pixelFormat));
1071 }
1072 result.append(" standards=\n");
1073 for (const auto& standard : combination.standards) {
1074 base::StringAppendF(&result, " %s (%d)\n",
1075 decodeStandardOnly(static_cast<uint32_t>(standard)).c_str(),
1076 static_cast<uint32_t>(standard));
1077 }
1078 result.append(" transfers=\n");
1079 for (const auto& transfer : combination.transfers) {
1080 base::StringAppendF(&result, " %s (%d)\n",
1081 decodeTransferOnly(static_cast<uint32_t>(transfer)).c_str(),
1082 static_cast<uint32_t>(transfer));
1083 }
1084 result.append(" ranges=\n");
1085 for (const auto& range : combination.ranges) {
1086 base::StringAppendF(&result, " %s (%d)\n",
1087 decodeRangeOnly(static_cast<uint32_t>(range)).c_str(),
1088 static_cast<uint32_t>(range));
1089 }
1090 result.append("\n");
1091 }
1092 }
1093
dump(std::string & result) const1094 void HWComposer::dump(std::string& result) const {
1095 result.append(mComposer->dumpDebugInfo());
1096 dumpOverlayProperties(result);
1097 }
1098
toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const1099 std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
1100 hal::HWDisplayId hwcDisplayId) const {
1101 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
1102 it != mPhysicalDisplayIdMap.end()) {
1103 return it->second;
1104 }
1105 return {};
1106 }
1107
fromPhysicalDisplayId(PhysicalDisplayId displayId) const1108 std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
1109 PhysicalDisplayId displayId) const {
1110 if (const auto it = mDisplayData.find(displayId); it != mDisplayData.end()) {
1111 return it->second.hwcDisplay->getId();
1112 }
1113 return {};
1114 }
1115
shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,bool hasDisplayIdentificationData) const1116 bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
1117 bool hasDisplayIdentificationData) const {
1118 if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
1119 ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
1120 hwcDisplayId);
1121 return true;
1122 }
1123
1124 // Legacy mode only supports IDs LEGACY_DISPLAY_TYPE_PRIMARY and LEGACY_DISPLAY_TYPE_EXTERNAL.
1125 if (!mHasMultiDisplaySupport && mPhysicalDisplayIdMap.size() == 2) {
1126 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
1127 return true;
1128 }
1129
1130 return false;
1131 }
1132
onHotplugConnect(hal::HWDisplayId hwcDisplayId)1133 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
1134 hal::HWDisplayId hwcDisplayId) {
1135 std::optional<DisplayIdentificationInfo> info;
1136 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
1137 info = DisplayIdentificationInfo{.id = *displayId,
1138 .name = std::string(),
1139 .deviceProductInfo = std::nullopt};
1140 if (mUpdateDeviceProductInfoOnHotplugReconnect) {
1141 uint8_t port;
1142 DisplayIdentificationData data;
1143 getDisplayIdentificationData(hwcDisplayId, &port, &data);
1144 if (auto newInfo = parseDisplayIdentificationData(port, data)) {
1145 info->deviceProductInfo = std::move(newInfo->deviceProductInfo);
1146 info->preferredDetailedTimingDescriptor =
1147 std::move(newInfo->preferredDetailedTimingDescriptor);
1148 } else {
1149 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
1150 }
1151 }
1152 } else {
1153 uint8_t port;
1154 DisplayIdentificationData data;
1155 const bool hasDisplayIdentificationData =
1156 getDisplayIdentificationData(hwcDisplayId, &port, &data);
1157 if (mPhysicalDisplayIdMap.empty()) {
1158 mHasMultiDisplaySupport = hasDisplayIdentificationData;
1159 ALOGI("Switching to %s multi-display mode",
1160 mHasMultiDisplaySupport ? "generalized" : "legacy");
1161 }
1162
1163 if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
1164 return {};
1165 }
1166
1167 info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
1168 const bool isPrimary = !mPrimaryHwcDisplayId;
1169 if (mHasMultiDisplaySupport) {
1170 if (const auto info = parseDisplayIdentificationData(port, data)) {
1171 return *info;
1172 }
1173 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
1174 } else {
1175 ALOGW_IF(hasDisplayIdentificationData,
1176 "Ignoring identification data for display %" PRIu64, hwcDisplayId);
1177 port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
1178 }
1179
1180 return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
1181 .name = isPrimary ? "Primary display"
1182 : "Secondary display",
1183 .deviceProductInfo = std::nullopt};
1184 }();
1185
1186 mComposer->onHotplugConnect(hwcDisplayId);
1187 }
1188
1189 if (!isConnected(info->id)) {
1190 std::optional<ui::Size> size = std::nullopt;
1191 if (info->preferredDetailedTimingDescriptor) {
1192 size = info->preferredDetailedTimingDescriptor->physicalSizeInMm;
1193 }
1194 allocatePhysicalDisplay(hwcDisplayId, info->id, size);
1195 }
1196 return info;
1197 }
1198
onHotplugDisconnect(hal::HWDisplayId hwcDisplayId)1199 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
1200 hal::HWDisplayId hwcDisplayId) {
1201 LOG_ALWAYS_FATAL_IF(hwcDisplayId == mPrimaryHwcDisplayId,
1202 "Primary display cannot be disconnected.");
1203
1204 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
1205 if (!displayId) {
1206 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
1207 return {};
1208 }
1209
1210 if (!isConnected(*displayId)) {
1211 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Already disconnected");
1212 return {};
1213 }
1214
1215 // The display will later be destroyed by a call to HWComposer::disconnectDisplay. For now, mark
1216 // it as disconnected.
1217 mDisplayData.at(*displayId).hwcDisplay->setConnected(false);
1218 mComposer->onHotplugDisconnect(hwcDisplayId);
1219 return DisplayIdentificationInfo{.id = *displayId};
1220 }
1221
loadCapabilities()1222 void HWComposer::loadCapabilities() {
1223 static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
1224 auto capabilities = mComposer->getCapabilities();
1225 for (auto capability : capabilities) {
1226 mCapabilities.emplace(capability);
1227 }
1228 }
1229
loadOverlayProperties()1230 void HWComposer::loadOverlayProperties() {
1231 mComposer->getOverlaySupport(&mOverlayProperties);
1232 }
1233
loadHdrConversionCapabilities()1234 void HWComposer::loadHdrConversionCapabilities() {
1235 const auto error = mComposer->getHdrConversionCapabilities(&mHdrConversionCapabilities);
1236 if (error != hal::Error::NONE) {
1237 ALOGE("Error in fetching HDR conversion capabilities %s", to_string(error).c_str());
1238 mHdrConversionCapabilities = {};
1239 }
1240 }
1241
setIdleTimerEnabled(PhysicalDisplayId displayId,std::chrono::milliseconds timeout)1242 status_t HWComposer::setIdleTimerEnabled(PhysicalDisplayId displayId,
1243 std::chrono::milliseconds timeout) {
1244 SFTRACE_CALL();
1245 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1246 const auto error = mDisplayData[displayId].hwcDisplay->setIdleTimerEnabled(timeout);
1247 if (error == hal::Error::UNSUPPORTED) {
1248 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1249 }
1250 if (error == hal::Error::BAD_PARAMETER) {
1251 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1252 }
1253 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1254 return NO_ERROR;
1255 }
1256
hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) const1257 bool HWComposer::hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) const {
1258 RETURN_IF_INVALID_DISPLAY(displayId, false);
1259 return mDisplayData.at(displayId).hwcDisplay->hasDisplayIdleTimerCapability();
1260 }
1261
getPhysicalDisplayOrientation(PhysicalDisplayId displayId) const1262 Hwc2::AidlTransform HWComposer::getPhysicalDisplayOrientation(PhysicalDisplayId displayId) const {
1263 SFTRACE_CALL();
1264 RETURN_IF_INVALID_DISPLAY(displayId, Hwc2::AidlTransform::NONE);
1265 Hwc2::AidlTransform outTransform;
1266 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
1267 const auto error = hwcDisplay->getPhysicalDisplayOrientation(&outTransform);
1268 RETURN_IF_HWC_ERROR(error, displayId, Hwc2::AidlTransform::NONE);
1269 return outTransform;
1270 }
1271
loadLayerMetadataSupport()1272 void HWComposer::loadLayerMetadataSupport() {
1273 mSupportedLayerGenericMetadata.clear();
1274
1275 std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo;
1276 const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo);
1277 if (error != hardware::graphics::composer::V2_4::Error::NONE) {
1278 if (error != hardware::graphics::composer::V2_4::Error::UNSUPPORTED) {
1279 ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
1280 toString(error).c_str(), static_cast<int32_t>(error));
1281 }
1282 return;
1283 }
1284
1285 for (const auto& [name, mandatory] : supportedMetadataKeyInfo) {
1286 mSupportedLayerGenericMetadata.emplace(name, mandatory);
1287 }
1288 }
1289
1290 } // namespace impl
1291 } // namespace android
1292
1293 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1294 #pragma clang diagnostic pop // ignored "-Wconversion"
1295