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,HotplugEvent event)140 std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
141 HotplugEvent event) {
142 switch (event) {
143 case HotplugEvent::Connected:
144 return onHotplugConnect(hwcDisplayId);
145 case HotplugEvent::Disconnected:
146 return onHotplugDisconnect(hwcDisplayId);
147 case HotplugEvent::LinkUnstable:
148 return onHotplugLinkTrainingFailure(hwcDisplayId);
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,uint8_t port,std::optional<ui::Size> physicalSize)227 void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, PhysicalDisplayId displayId,
228 uint8_t port, std::optional<ui::Size> physicalSize) {
229 LOG_ALWAYS_FATAL_IF(!mActivePorts.try_emplace(port).second,
230 "Cannot attach display %" PRIu64 " to an already active port %" PRIu8 ".",
231 hwcDisplayId, port);
232
233 mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
234
235 if (!mPrimaryHwcDisplayId) {
236 mPrimaryHwcDisplayId = hwcDisplayId;
237 }
238
239 auto& displayData = mDisplayData[displayId];
240 auto newDisplay =
241 std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
242 hal::DisplayType::PHYSICAL);
243 newDisplay->setConnected(true);
244 newDisplay->setPhysicalSizeInMm(physicalSize);
245 displayData.hwcDisplay = std::move(newDisplay);
246 displayData.port = port;
247 }
248
getAttribute(hal::HWDisplayId hwcDisplayId,hal::HWConfigId configId,hal::Attribute attribute) const249 int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
250 hal::Attribute attribute) const {
251 int32_t value = 0;
252 auto error = static_cast<hal::Error>(
253 mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
254
255 RETURN_IF_HWC_ERROR_FOR("getDisplayAttribute", error, *toPhysicalDisplayId(hwcDisplayId), -1);
256 return value;
257 }
258
createLayer(HalDisplayId displayId)259 std::shared_ptr<HWC2::Layer> HWComposer::createLayer(HalDisplayId displayId) {
260 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
261
262 auto expected = mDisplayData[displayId].hwcDisplay->createLayer();
263 if (!expected.has_value()) {
264 auto error = std::move(expected).error();
265 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
266 }
267 return std::move(expected).value();
268 }
269
isConnected(PhysicalDisplayId displayId) const270 bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
271 return mDisplayData.count(displayId) && mDisplayData.at(displayId).hwcDisplay->isConnected();
272 }
273
getModes(PhysicalDisplayId displayId,int32_t maxFrameIntervalNs) const274 std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId,
275 int32_t maxFrameIntervalNs) const {
276 RETURN_IF_INVALID_DISPLAY(displayId, {});
277
278 const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
279
280 if (mComposer->isVrrSupported()) {
281 return getModesFromDisplayConfigurations(hwcDisplayId, maxFrameIntervalNs);
282 }
283
284 return getModesFromLegacyDisplayConfigs(hwcDisplayId);
285 }
286
getEstimatedDotsPerInchFromSize(uint64_t hwcDisplayId,const HWCDisplayMode & hwcMode) const287 DisplayConfiguration::Dpi HWComposer::getEstimatedDotsPerInchFromSize(
288 uint64_t hwcDisplayId, const HWCDisplayMode& hwcMode) const {
289 if (!FlagManager::getInstance().correct_dpi_with_display_size()) {
290 return {-1, -1};
291 }
292 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
293 if (const auto it = mDisplayData.find(displayId.value());
294 it != mDisplayData.end() && it->second.hwcDisplay->getPhysicalSizeInMm()) {
295 ui::Size size = it->second.hwcDisplay->getPhysicalSizeInMm().value();
296 if (hwcMode.width > 0 && hwcMode.height > 0 && size.width > 0 && size.height > 0) {
297 static constexpr float kMmPerInch = 25.4f;
298 return {hwcMode.width * kMmPerInch / size.width,
299 hwcMode.height * kMmPerInch / size.height};
300 }
301 }
302 }
303 return {-1, -1};
304 }
305
correctedDpiIfneeded(DisplayConfiguration::Dpi dpi,DisplayConfiguration::Dpi estimatedDpi) const306 DisplayConfiguration::Dpi HWComposer::correctedDpiIfneeded(
307 DisplayConfiguration::Dpi dpi, DisplayConfiguration::Dpi estimatedDpi) const {
308 // hwc can be unreliable when it comes to dpi. A rough estimated dpi may yield better
309 // results. For instance, libdrm and bad edid may result in a dpi of {350, 290} for a
310 // 16:9 3840x2160 display, which would match a 4:3 aspect ratio.
311 // The logic here checks if hwc was able to provide some dpi, and if so if the dpi
312 // disparity between the axes is more reasonable than a rough estimate, otherwise use
313 // the estimated dpi as a corrected value.
314 if (estimatedDpi.x == -1 || estimatedDpi.y == -1) {
315 return dpi;
316 }
317 if (dpi.x == -1 || dpi.y == -1) {
318 return estimatedDpi;
319 }
320 if (std::min(dpi.x, dpi.y) != 0 && std::min(estimatedDpi.x, estimatedDpi.y) != 0 &&
321 abs(dpi.x - dpi.y) / std::min(dpi.x, dpi.y) >
322 abs(estimatedDpi.x - estimatedDpi.y) / std::min(estimatedDpi.x, estimatedDpi.y)) {
323 return estimatedDpi;
324 }
325 return dpi;
326 }
327
getModesFromDisplayConfigurations(uint64_t hwcDisplayId,int32_t maxFrameIntervalNs) const328 std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromDisplayConfigurations(
329 uint64_t hwcDisplayId, int32_t maxFrameIntervalNs) const {
330 std::vector<hal::DisplayConfiguration> configs;
331 auto error = static_cast<hal::Error>(
332 mComposer->getDisplayConfigurations(hwcDisplayId, maxFrameIntervalNs, &configs));
333 RETURN_IF_HWC_ERROR_FOR("getDisplayConfigurations", error, *toPhysicalDisplayId(hwcDisplayId),
334 {});
335
336 std::vector<HWCDisplayMode> modes;
337 modes.reserve(configs.size());
338 for (auto config : configs) {
339 auto hwcMode = HWCDisplayMode{.hwcId = static_cast<hal::HWConfigId>(config.configId),
340 .width = config.width,
341 .height = config.height,
342 .vsyncPeriod = config.vsyncPeriod,
343 .configGroup = config.configGroup,
344 .vrrConfig = config.vrrConfig,
345 .hdrOutputType = config.hdrOutputType};
346
347 const DisplayConfiguration::Dpi estimatedDPI =
348 getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
349 if (config.dpi) {
350 const DisplayConfiguration::Dpi dpi =
351 correctedDpiIfneeded(config.dpi.value(), estimatedDPI);
352 hwcMode.dpiX = dpi.x;
353 hwcMode.dpiY = dpi.y;
354 } else if (estimatedDPI.x != -1 && estimatedDPI.y != -1) {
355 hwcMode.dpiX = estimatedDPI.x;
356 hwcMode.dpiY = estimatedDPI.y;
357 }
358
359 if (!mEnableVrrTimeout) {
360 hwcMode.vrrConfig->notifyExpectedPresentConfig = {};
361 }
362
363 modes.push_back(hwcMode);
364 }
365
366 return modes;
367 }
368
getModesFromLegacyDisplayConfigs(uint64_t hwcDisplayId) const369 std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromLegacyDisplayConfigs(
370 uint64_t hwcDisplayId) const {
371 std::vector<hal::HWConfigId> configIds;
372 auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
373 RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
374
375 std::vector<HWCDisplayMode> modes;
376 modes.reserve(configIds.size());
377 for (auto configId : configIds) {
378 auto hwcMode = HWCDisplayMode{
379 .hwcId = configId,
380 .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
381 .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
382 .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
383 .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
384 };
385
386 const int32_t dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X);
387 const int32_t dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y);
388 const DisplayConfiguration::Dpi hwcDpi =
389 DisplayConfiguration::Dpi{dpiX == -1 ? dpiX : dpiX / 1000.f,
390 dpiY == -1 ? dpiY : dpiY / 1000.f};
391 const DisplayConfiguration::Dpi estimatedDPI =
392 getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
393 const DisplayConfiguration::Dpi dpi = correctedDpiIfneeded(hwcDpi, estimatedDPI);
394 hwcMode.dpiX = dpi.x;
395 hwcMode.dpiY = dpi.y;
396
397 modes.push_back(hwcMode);
398 }
399 return modes;
400 }
401
getActiveMode(PhysicalDisplayId displayId) const402 ftl::Expected<hal::HWConfigId, status_t> HWComposer::getActiveMode(
403 PhysicalDisplayId displayId) const {
404 RETURN_IF_INVALID_DISPLAY(displayId, ftl::Unexpected(BAD_INDEX));
405 const auto hwcId = *fromPhysicalDisplayId(displayId);
406
407 hal::HWConfigId configId;
408 const auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
409 if (error == hal::Error::BAD_CONFIG) {
410 return ftl::Unexpected(NO_INIT);
411 }
412
413 RETURN_IF_HWC_ERROR_FOR("getActiveConfig", error, displayId, ftl::Unexpected(UNKNOWN_ERROR));
414 return configId;
415 }
416
417 // Composer 2.4
418
getDisplayConnectionType(PhysicalDisplayId displayId) const419 ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
420 RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal);
421 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
422
423 if (const auto connectionType = hwcDisplay->getConnectionType()) {
424 return connectionType.value();
425 } else {
426 LOG_HWC_ERROR(__func__, connectionType.error(), displayId);
427 return hwcDisplay->getId() == mPrimaryHwcDisplayId ? ui::DisplayConnectionType::Internal
428 : ui::DisplayConnectionType::External;
429 }
430 }
431
isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const432 bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const {
433 RETURN_IF_INVALID_DISPLAY(displayId, false);
434 return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
435 }
436
getDisplayVsyncPeriod(PhysicalDisplayId displayId) const437 ftl::Expected<nsecs_t, status_t> HWComposer::getDisplayVsyncPeriod(
438 PhysicalDisplayId displayId) const {
439 RETURN_IF_INVALID_DISPLAY(displayId, ftl::Unexpected(BAD_INDEX));
440
441 if (!isVsyncPeriodSwitchSupported(displayId)) {
442 return ftl::Unexpected(INVALID_OPERATION);
443 }
444
445 const auto hwcId = *fromPhysicalDisplayId(displayId);
446 Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
447 const auto error =
448 static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
449 RETURN_IF_HWC_ERROR(error, displayId, ftl::Unexpected(UNKNOWN_ERROR));
450 return static_cast<nsecs_t>(vsyncPeriodNanos);
451 }
452
getColorModes(PhysicalDisplayId displayId) const453 std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
454 RETURN_IF_INVALID_DISPLAY(displayId, {});
455
456 std::vector<ui::ColorMode> modes;
457 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
458 RETURN_IF_HWC_ERROR(error, displayId, {});
459 return modes;
460 }
461
setActiveColorMode(PhysicalDisplayId displayId,ui::ColorMode mode,ui::RenderIntent renderIntent)462 status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode,
463 ui::RenderIntent renderIntent) {
464 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
465
466 auto& displayData = mDisplayData[displayId];
467 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
468 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
469 decodeRenderIntent(renderIntent) + ")")
470 .c_str(),
471 error, displayId, UNKNOWN_ERROR);
472
473 return NO_ERROR;
474 }
475
setVsyncEnabled(PhysicalDisplayId displayId,hal::Vsync enabled)476 void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) {
477 RETURN_IF_INVALID_DISPLAY(displayId);
478 auto& displayData = mDisplayData[displayId];
479
480 // NOTE: we use our own internal lock here because we have to call
481 // into the HWC with the lock held, and we want to make sure
482 // that even if HWC blocks (which it shouldn't), it won't
483 // affect other threads.
484 std::lock_guard lock(displayData.vsyncEnabledLock);
485 if (enabled == displayData.vsyncEnabled) {
486 return;
487 }
488
489 SFTRACE_CALL();
490 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
491 RETURN_IF_HWC_ERROR(error, displayId);
492
493 displayData.vsyncEnabled = enabled;
494
495 SFTRACE_INT(ftl::Concat("HW_VSYNC_ON_", displayId.value).c_str(),
496 enabled == hal::Vsync::ENABLE ? 1 : 0);
497 }
498
setClientTarget(HalDisplayId displayId,uint32_t slot,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & target,ui::Dataspace dataspace,float hdrSdrRatio)499 status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot,
500 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
501 ui::Dataspace dataspace, float hdrSdrRatio) {
502 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
503
504 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
505 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
506 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace, hdrSdrRatio);
507 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
508 return NO_ERROR;
509 }
510
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)511 status_t HWComposer::getDeviceCompositionChanges(
512 HalDisplayId displayId, bool frameUsesClientComposition,
513 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime,
514 nsecs_t expectedPresentTime, Fps frameInterval,
515 std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
516 SFTRACE_CALL();
517
518 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
519
520 auto& displayData = mDisplayData[displayId];
521 auto& hwcDisplay = displayData.hwcDisplay;
522 if (!hwcDisplay->isConnected()) {
523 return NO_ERROR;
524 }
525
526 uint32_t numTypes = 0;
527 uint32_t numRequests = 0;
528
529 hal::Error error = hal::Error::NONE;
530
531 // First try to skip validate altogether. We can do that when
532 // 1. The previous frame has not been presented yet or already passed the
533 // earliest time to present. Otherwise, we may present a frame too early.
534 // 2. There is no client composition. Otherwise, we first need to render the
535 // client target buffer.
536 const bool canSkipValidate = [&] {
537 // We must call validate if we have client composition
538 if (frameUsesClientComposition) {
539 return false;
540 }
541
542 // If composer supports getting the expected present time, we can skip
543 // as composer will make sure to prevent early presentation
544 if (!earliestPresentTime) {
545 return true;
546 }
547
548 // composer doesn't support getting the expected present time. We can only
549 // skip validate if we know that we are not going to present early.
550 return std::chrono::steady_clock::now() >= *earliestPresentTime;
551 }();
552
553 displayData.validateWasSkipped = false;
554 SFTRACE_FORMAT("NextFrameInterval %d_Hz", frameInterval.getIntValue());
555 if (canSkipValidate) {
556 sp<Fence> outPresentFence = Fence::NO_FENCE;
557 uint32_t state = UINT32_MAX;
558 error = hwcDisplay->presentOrValidate(expectedPresentTime, frameInterval.getPeriodNsecs(),
559 &numTypes, &numRequests, &outPresentFence, &state);
560 if (!hasChangesError(error)) {
561 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
562 }
563 if (state == 1) { // Present Succeeded.
564 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
565 error = hwcDisplay->getReleaseFences(&releaseFences);
566 displayData.releaseFences = std::move(releaseFences);
567 displayData.lastPresentFence = outPresentFence;
568 displayData.validateWasSkipped = true;
569 displayData.presentError = error;
570 return NO_ERROR;
571 }
572 // Present failed but Validate ran.
573 } else {
574 error = hwcDisplay->validate(expectedPresentTime, frameInterval.getPeriodNsecs(), &numTypes,
575 &numRequests);
576 }
577 ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
578 if (!hasChangesError(error)) {
579 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
580 }
581
582 android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
583 changedTypes.reserve(numTypes);
584 error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
585 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
586
587 auto displayRequests = static_cast<hal::DisplayRequest>(0);
588 android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
589 layerRequests.reserve(numRequests);
590 error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
591 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
592
593 DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
594 error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
595 RETURN_IF_HWC_ERROR_FOR("getClientTargetProperty", error, displayId, BAD_INDEX);
596
597 DeviceRequestedChanges::LayerLuts layerLuts;
598 error = hwcDisplay->getRequestedLuts(&layerLuts, mLutFileDescriptorMapper);
599 RETURN_IF_HWC_ERROR_FOR("getRequestedLuts", error, displayId, BAD_INDEX);
600
601 outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
602 std::move(layerRequests),
603 std::move(clientTargetProperty),
604 std::move(layerLuts)});
605 error = hwcDisplay->acceptChanges();
606 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
607
608 return NO_ERROR;
609 }
610
getPresentFence(HalDisplayId displayId) const611 sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const {
612 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
613 return mDisplayData.at(displayId).lastPresentFence;
614 }
615
getPresentTimestamp(PhysicalDisplayId displayId) const616 nsecs_t HWComposer::getPresentTimestamp(PhysicalDisplayId displayId) const {
617 RETURN_IF_INVALID_DISPLAY(displayId, 0);
618 return mDisplayData.at(displayId).lastPresentTimestamp;
619 }
620
getLayerReleaseFence(HalDisplayId displayId,HWC2::Layer * layer) const621 sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
622 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
623 const auto& displayFences = mDisplayData.at(displayId).releaseFences;
624 auto fence = displayFences.find(layer);
625 if (fence == displayFences.end()) {
626 ALOGV("getLayerReleaseFence: Release fence not found");
627 return Fence::NO_FENCE;
628 }
629 return fence->second;
630 }
631
presentAndGetReleaseFences(HalDisplayId displayId,std::optional<std::chrono::steady_clock::time_point> earliestPresentTime)632 status_t HWComposer::presentAndGetReleaseFences(
633 HalDisplayId displayId,
634 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) {
635 SFTRACE_CALL();
636
637 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
638
639 auto& displayData = mDisplayData[displayId];
640 auto& hwcDisplay = displayData.hwcDisplay;
641
642 if (displayData.validateWasSkipped) {
643 // explicitly flush all pending commands
644 auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
645 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
646 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
647 return NO_ERROR;
648 }
649
650 if (earliestPresentTime) {
651 SFTRACE_NAME("wait for earliest present time");
652 std::this_thread::sleep_until(*earliestPresentTime);
653 }
654
655 auto error = hwcDisplay->present(&displayData.lastPresentFence);
656 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
657
658 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
659 error = hwcDisplay->getReleaseFences(&releaseFences);
660 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
661
662 displayData.releaseFences = std::move(releaseFences);
663
664 return NO_ERROR;
665 }
666
executeCommands(HalDisplayId displayId)667 status_t HWComposer::executeCommands(HalDisplayId displayId) {
668 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
669 auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
670 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
671 return NO_ERROR;
672 }
673
setPowerMode(PhysicalDisplayId displayId,hal::PowerMode mode)674 status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
675 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
676
677 if (mode == hal::PowerMode::OFF) {
678 setVsyncEnabled(displayId, hal::Vsync::DISABLE);
679 }
680
681 const auto& displayData = mDisplayData[displayId];
682 auto& hwcDisplay = displayData.hwcDisplay;
683 switch (mode) {
684 case hal::PowerMode::OFF:
685 case hal::PowerMode::ON:
686 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
687 {
688 auto error = hwcDisplay->setPowerMode(mode);
689 if (error != hal::Error::NONE) {
690 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
691 displayId);
692 }
693 }
694 break;
695 case hal::PowerMode::DOZE:
696 case hal::PowerMode::DOZE_SUSPEND:
697 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
698 {
699 bool supportsDoze = false;
700 const auto queryDozeError = hwcDisplay->supportsDoze(&supportsDoze);
701
702 // queryDozeError might be NO_RESOURCES, in the case of a display that has never
703 // been turned on. In that case, attempt to set to DOZE anyway.
704 if (!supportsDoze && queryDozeError == hal::Error::NONE) {
705 mode = hal::PowerMode::ON;
706 }
707
708 auto error = hwcDisplay->setPowerMode(mode);
709 if (error != hal::Error::NONE) {
710 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
711 displayId);
712 // If the display had never been turned on, so its doze
713 // support was unknown, it may truly not support doze. Try
714 // switching it to ON instead.
715 if (queryDozeError == hal::Error::NO_RESOURCES) {
716 ALOGD("%s: failed to set %s to %s. Trying again with ON", __func__,
717 to_string(displayId).c_str(), to_string(mode).c_str());
718 error = hwcDisplay->setPowerMode(hal::PowerMode::ON);
719 if (error != hal::Error::NONE) {
720 LOG_HWC_ERROR("setPowerMode(ON)", error, displayId);
721 }
722 }
723 }
724 }
725 break;
726 default:
727 ALOGV("setPowerMode: Not calling HWC");
728 break;
729 }
730
731 return NO_ERROR;
732 }
733
setActiveModeWithConstraints(PhysicalDisplayId displayId,hal::HWConfigId hwcModeId,const hal::VsyncPeriodChangeConstraints & constraints,hal::VsyncPeriodChangeTimeline * outTimeline)734 status_t HWComposer::setActiveModeWithConstraints(
735 PhysicalDisplayId displayId, hal::HWConfigId hwcModeId,
736 const hal::VsyncPeriodChangeConstraints& constraints,
737 hal::VsyncPeriodChangeTimeline* outTimeline) {
738 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
739
740 auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
741 constraints,
742 outTimeline);
743 if (error == hal::Error::CONFIG_FAILED) {
744 RETURN_IF_HWC_ERROR_FOR("setActiveConfigWithConstraints", error, displayId,
745 FAILED_TRANSACTION);
746 }
747 RETURN_IF_HWC_ERROR_FOR("setActiveConfigWithConstraints", error, displayId, UNKNOWN_ERROR);
748 return NO_ERROR;
749 }
750
setColorTransform(HalDisplayId displayId,const mat4 & transform)751 status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) {
752 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
753
754 auto& displayData = mDisplayData[displayId];
755 auto error = displayData.hwcDisplay->setColorTransform(transform);
756 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
757 return NO_ERROR;
758 }
759
disconnectDisplay(HalDisplayId displayId)760 void HWComposer::disconnectDisplay(HalDisplayId displayId) {
761 RETURN_IF_INVALID_DISPLAY(displayId);
762 auto& displayData = mDisplayData[displayId];
763 const auto hwcDisplayId = displayData.hwcDisplay->getId();
764
765 mPhysicalDisplayIdMap.erase(hwcDisplayId);
766 if (const auto port = displayData.port) {
767 mActivePorts.erase(port.value());
768 }
769 mDisplayData.erase(displayId);
770
771 // Reset the primary display ID if we're disconnecting it.
772 // This way isHeadless() will return false, which is necessary
773 // because getPrimaryDisplayId() will crash.
774 if (mPrimaryHwcDisplayId == hwcDisplayId) {
775 mPrimaryHwcDisplayId.reset();
776 }
777 }
778
setOutputBuffer(HalVirtualDisplayId displayId,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & buffer)779 status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
780 const sp<GraphicBuffer>& buffer) {
781 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
782 const auto& displayData = mDisplayData[displayId];
783
784 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
785 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
786 return NO_ERROR;
787 }
788
clearReleaseFences(HalDisplayId displayId)789 void HWComposer::clearReleaseFences(HalDisplayId displayId) {
790 RETURN_IF_INVALID_DISPLAY(displayId);
791 mDisplayData[displayId].releaseFences.clear();
792 }
793
getHdrCapabilities(HalDisplayId displayId,HdrCapabilities * outCapabilities)794 status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) {
795 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
796
797 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
798 auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
799 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
800 return NO_ERROR;
801 }
802
803 const aidl::android::hardware::graphics::composer3::OverlayProperties&
getOverlaySupport() const804 HWComposer::getOverlaySupport() const {
805 return mOverlayProperties;
806 }
807
getSupportedPerFrameMetadata(HalDisplayId displayId) const808 int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const {
809 RETURN_IF_INVALID_DISPLAY(displayId, 0);
810 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
811 }
812
getRenderIntents(HalDisplayId displayId,ui::ColorMode colorMode) const813 std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId,
814 ui::ColorMode colorMode) const {
815 RETURN_IF_INVALID_DISPLAY(displayId, {});
816
817 std::vector<ui::RenderIntent> renderIntents;
818 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
819 RETURN_IF_HWC_ERROR(error, displayId, {});
820 return renderIntents;
821 }
822
getDataspaceSaturationMatrix(HalDisplayId displayId,ui::Dataspace dataspace)823 mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) {
824 RETURN_IF_INVALID_DISPLAY(displayId, {});
825
826 mat4 matrix;
827 auto error =
828 mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace, &matrix);
829 RETURN_IF_HWC_ERROR(error, displayId, {});
830 return matrix;
831 }
832
getDisplayedContentSamplingAttributes(HalDisplayId displayId,ui::PixelFormat * outFormat,ui::Dataspace * outDataspace,uint8_t * outComponentMask)833 status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId,
834 ui::PixelFormat* outFormat,
835 ui::Dataspace* outDataspace,
836 uint8_t* outComponentMask) {
837 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
838 const auto error =
839 mDisplayData[displayId]
840 .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
841 outComponentMask);
842 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
843 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
844 return NO_ERROR;
845 }
846
setDisplayContentSamplingEnabled(HalDisplayId displayId,bool enabled,uint8_t componentMask,uint64_t maxFrames)847 status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled,
848 uint8_t componentMask, uint64_t maxFrames) {
849 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
850 const auto error =
851 mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
852 componentMask,
853 maxFrames);
854
855 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
856 if (error == hal::Error::BAD_PARAMETER) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
857 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
858 return NO_ERROR;
859 }
860
getDisplayedContentSample(HalDisplayId displayId,uint64_t maxFrames,uint64_t timestamp,DisplayedFrameStats * outStats)861 status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames,
862 uint64_t timestamp, DisplayedFrameStats* outStats) {
863 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
864 const auto error =
865 mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
866 outStats);
867 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
868 return NO_ERROR;
869 }
870
setDisplayBrightness(PhysicalDisplayId displayId,float brightness,float brightnessNits,const Hwc2::Composer::DisplayBrightnessOptions & options)871 ftl::Future<status_t> HWComposer::setDisplayBrightness(
872 PhysicalDisplayId displayId, float brightness, float brightnessNits,
873 const Hwc2::Composer::DisplayBrightnessOptions& options) {
874 RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX));
875 auto& display = mDisplayData[displayId].hwcDisplay;
876
877 return display->setDisplayBrightness(brightness, brightnessNits, options)
878 .then([displayId](hal::Error error) -> status_t {
879 if (error == hal::Error::UNSUPPORTED) {
880 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
881 }
882 if (error == hal::Error::BAD_PARAMETER) {
883 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
884 }
885 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
886 return NO_ERROR;
887 });
888 }
889
getValidateSkipped(HalDisplayId displayId) const890 bool HWComposer::getValidateSkipped(HalDisplayId displayId) const {
891 if (mDisplayData.count(displayId) == 0) {
892 return false;
893 }
894 return mDisplayData.at(displayId).validateWasSkipped;
895 }
896
setBootDisplayMode(PhysicalDisplayId displayId,hal::HWConfigId displayModeId)897 status_t HWComposer::setBootDisplayMode(PhysicalDisplayId displayId,
898 hal::HWConfigId displayModeId) {
899 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
900 const auto error = mDisplayData[displayId].hwcDisplay->setBootDisplayConfig(displayModeId);
901 if (error == hal::Error::UNSUPPORTED) {
902 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
903 }
904 if (error == hal::Error::BAD_PARAMETER) {
905 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
906 }
907 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
908 return NO_ERROR;
909 }
910
clearBootDisplayMode(PhysicalDisplayId displayId)911 status_t HWComposer::clearBootDisplayMode(PhysicalDisplayId displayId) {
912 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
913 const auto error = mDisplayData[displayId].hwcDisplay->clearBootDisplayConfig();
914 if (error == hal::Error::UNSUPPORTED) {
915 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
916 }
917 if (error == hal::Error::BAD_PARAMETER) {
918 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
919 }
920 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
921 return NO_ERROR;
922 }
923
getPreferredBootDisplayMode(PhysicalDisplayId displayId)924 std::optional<hal::HWConfigId> HWComposer::getPreferredBootDisplayMode(
925 PhysicalDisplayId displayId) {
926 RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
927 hal::HWConfigId displayModeId;
928 const auto error =
929 mDisplayData[displayId].hwcDisplay->getPreferredBootDisplayConfig(&displayModeId);
930 if (error != hal::Error::NONE) {
931 LOG_DISPLAY_ERROR(displayId, to_string(error).c_str());
932 return std::nullopt;
933 }
934 return displayModeId;
935 }
936
getHdrConversionCapabilities() const937 std::vector<HdrConversionCapability> HWComposer::getHdrConversionCapabilities() const {
938 return mHdrConversionCapabilities;
939 }
940
setHdrConversionStrategy(HdrConversionStrategy hdrConversionStrategy,aidl::android::hardware::graphics::common::Hdr * outPreferredHdrOutputType)941 status_t HWComposer::setHdrConversionStrategy(
942 HdrConversionStrategy hdrConversionStrategy,
943 aidl::android::hardware::graphics::common::Hdr* outPreferredHdrOutputType) {
944 const auto error =
945 mComposer->setHdrConversionStrategy(hdrConversionStrategy, outPreferredHdrOutputType);
946 if (error != hal::Error::NONE) {
947 ALOGE("Error in setting HDR conversion strategy %s", to_string(error).c_str());
948 return INVALID_OPERATION;
949 }
950 return NO_ERROR;
951 }
952
setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId displayId,bool enabled)953 status_t HWComposer::setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId displayId,
954 bool enabled) {
955 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
956 const auto error =
957 mComposer->setRefreshRateChangedCallbackDebugEnabled(mDisplayData[displayId]
958 .hwcDisplay->getId(),
959 enabled);
960 if (error != hal::Error::NONE) {
961 ALOGE("Error in setting refresh refresh rate change callback debug enabled %s",
962 to_string(error).c_str());
963 return INVALID_OPERATION;
964 }
965 return NO_ERROR;
966 }
967
notifyExpectedPresent(PhysicalDisplayId displayId,TimePoint expectedPresentTime,Fps frameInterval)968 status_t HWComposer::notifyExpectedPresent(PhysicalDisplayId displayId,
969 TimePoint expectedPresentTime, Fps frameInterval) {
970 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
971 SFTRACE_FORMAT("%s ExpectedPresentTime in %.2fms frameInterval %.2fms", __func__,
972 ticks<std::milli, float>(expectedPresentTime - TimePoint::now()),
973 ticks<std::milli, float>(Duration::fromNs(frameInterval.getPeriodNsecs())));
974 const auto error = mComposer->notifyExpectedPresent(mDisplayData[displayId].hwcDisplay->getId(),
975 expectedPresentTime.ns(),
976 frameInterval.getPeriodNsecs());
977 if (error != hal::Error::NONE) {
978 ALOGE("Error in notifyExpectedPresent call %s", to_string(error).c_str());
979 return INVALID_OPERATION;
980 }
981 return NO_ERROR;
982 }
983
getDisplayDecorationSupport(PhysicalDisplayId displayId,std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport> * support)984 status_t HWComposer::getDisplayDecorationSupport(
985 PhysicalDisplayId displayId,
986 std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
987 support) {
988 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
989 const auto error = mDisplayData[displayId].hwcDisplay->getDisplayDecorationSupport(support);
990 if (error == hal::Error::UNSUPPORTED) {
991 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
992 }
993 if (error == hal::Error::BAD_PARAMETER) {
994 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
995 }
996 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
997 return NO_ERROR;
998 }
999
setAutoLowLatencyMode(PhysicalDisplayId displayId,bool on)1000 status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
1001 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1002 const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
1003 if (error == hal::Error::UNSUPPORTED) {
1004 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1005 }
1006 if (error == hal::Error::BAD_PARAMETER) {
1007 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1008 }
1009 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1010 return NO_ERROR;
1011 }
1012
getSupportedContentTypes(PhysicalDisplayId displayId,std::vector<hal::ContentType> * outSupportedContentTypes) const1013 status_t HWComposer::getSupportedContentTypes(
1014 PhysicalDisplayId displayId,
1015 std::vector<hal::ContentType>* outSupportedContentTypes) const {
1016 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1017 const auto error = mDisplayData.at(displayId).hwcDisplay->getSupportedContentTypes(
1018 outSupportedContentTypes);
1019
1020 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1021
1022 return NO_ERROR;
1023 }
1024
setContentType(PhysicalDisplayId displayId,hal::ContentType contentType)1025 status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) {
1026 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1027 const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
1028 if (error == hal::Error::UNSUPPORTED) {
1029 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1030 }
1031 if (error == hal::Error::BAD_PARAMETER) {
1032 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1033 }
1034 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1035
1036 return NO_ERROR;
1037 }
1038
getMaxLayerPictureProfiles(PhysicalDisplayId displayId)1039 int32_t HWComposer::getMaxLayerPictureProfiles(PhysicalDisplayId displayId) {
1040 int32_t maxProfiles = 0;
1041 RETURN_IF_INVALID_DISPLAY(displayId, 0);
1042 const auto error = mDisplayData[displayId].hwcDisplay->getMaxLayerPictureProfiles(&maxProfiles);
1043 RETURN_IF_HWC_ERROR(error, displayId, 0);
1044 return maxProfiles;
1045 }
1046
setDisplayPictureProfileHandle(PhysicalDisplayId displayId,const PictureProfileHandle & handle)1047 status_t HWComposer::setDisplayPictureProfileHandle(PhysicalDisplayId displayId,
1048 const PictureProfileHandle& handle) {
1049 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1050 const auto error = mDisplayData[displayId].hwcDisplay->setPictureProfileHandle(handle);
1051 if (error != hal::Error::UNSUPPORTED) {
1052 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1053 }
1054 return NO_ERROR;
1055 }
1056
startHdcpNegotiation(PhysicalDisplayId displayId,const aidl::android::hardware::drm::HdcpLevels & levels)1057 status_t HWComposer::startHdcpNegotiation(PhysicalDisplayId displayId,
1058 const aidl::android::hardware::drm::HdcpLevels& levels) {
1059 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1060 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
1061 auto error = hwcDisplay->startHdcpNegotiation(levels);
1062 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1063 return NO_ERROR;
1064 }
1065
getLuts(PhysicalDisplayId displayId,const std::vector<sp<GraphicBuffer>> & buffers,std::vector<aidl::android::hardware::graphics::composer3::Luts> * luts)1066 status_t HWComposer::getLuts(
1067 PhysicalDisplayId displayId, const std::vector<sp<GraphicBuffer>>& buffers,
1068 std::vector<aidl::android::hardware::graphics::composer3::Luts>* luts) {
1069 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1070 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
1071 auto error = hwcDisplay->getLuts(buffers, luts);
1072 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1073 return NO_ERROR;
1074 }
1075
getSupportedLayerGenericMetadata() const1076 const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
1077 return mSupportedLayerGenericMetadata;
1078 }
1079
1080 ftl::SmallMap<HWC2::Layer*, ::android::base::unique_fd, 20>&
getLutFileDescriptorMapper()1081 HWComposer::getLutFileDescriptorMapper() {
1082 return mLutFileDescriptorMapper;
1083 }
1084
dumpOverlayProperties(std::string & result) const1085 void HWComposer::dumpOverlayProperties(std::string& result) const {
1086 // dump overlay properties
1087 result.append("OverlayProperties:\n");
1088 base::StringAppendF(&result, "supportMixedColorSpaces: %d\n",
1089 mOverlayProperties.supportMixedColorSpaces);
1090 base::StringAppendF(&result, "SupportedBufferCombinations(%zu entries)\n",
1091 mOverlayProperties.combinations.size());
1092 for (const auto& combination : mOverlayProperties.combinations) {
1093 result.append(" pixelFormats=\n");
1094 for (const auto& pixelFormat : combination.pixelFormats) {
1095 base::StringAppendF(&result, " %s (%d)\n",
1096 decodePixelFormat(static_cast<PixelFormat>(pixelFormat)).c_str(),
1097 static_cast<uint32_t>(pixelFormat));
1098 }
1099 result.append(" standards=\n");
1100 for (const auto& standard : combination.standards) {
1101 base::StringAppendF(&result, " %s (%d)\n",
1102 decodeStandardOnly(static_cast<uint32_t>(standard)).c_str(),
1103 static_cast<uint32_t>(standard));
1104 }
1105 result.append(" transfers=\n");
1106 for (const auto& transfer : combination.transfers) {
1107 base::StringAppendF(&result, " %s (%d)\n",
1108 decodeTransferOnly(static_cast<uint32_t>(transfer)).c_str(),
1109 static_cast<uint32_t>(transfer));
1110 }
1111 result.append(" ranges=\n");
1112 for (const auto& range : combination.ranges) {
1113 base::StringAppendF(&result, " %s (%d)\n",
1114 decodeRangeOnly(static_cast<uint32_t>(range)).c_str(),
1115 static_cast<uint32_t>(range));
1116 }
1117 result.append("\n");
1118 }
1119 }
1120
dump(std::string & result) const1121 void HWComposer::dump(std::string& result) const {
1122 result.append(mComposer->dumpDebugInfo());
1123 dumpOverlayProperties(result);
1124 }
1125
toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const1126 std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
1127 hal::HWDisplayId hwcDisplayId) const {
1128 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
1129 it != mPhysicalDisplayIdMap.end()) {
1130 return it->second;
1131 }
1132 return {};
1133 }
1134
fromPhysicalDisplayId(PhysicalDisplayId displayId) const1135 std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
1136 PhysicalDisplayId displayId) const {
1137 if (const auto it = mDisplayData.find(displayId); it != mDisplayData.end()) {
1138 return it->second.hwcDisplay->getId();
1139 }
1140 return {};
1141 }
1142
shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,uint8_t port,bool hasDisplayIdentificationData) const1143 bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId, uint8_t port,
1144 bool hasDisplayIdentificationData) const {
1145 if (mActivePorts.contains(port)) {
1146 ALOGE("Ignoring connection of display %" PRIu64 ". Port %" PRIu8
1147 " is already in active use.",
1148 hwcDisplayId, port);
1149 return true;
1150 }
1151
1152 if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
1153 ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
1154 hwcDisplayId);
1155 return true;
1156 }
1157
1158 // Legacy mode only supports IDs LEGACY_DISPLAY_TYPE_PRIMARY and LEGACY_DISPLAY_TYPE_EXTERNAL.
1159 if (!mHasMultiDisplaySupport && mPhysicalDisplayIdMap.size() == 2) {
1160 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
1161 return true;
1162 }
1163
1164 return false;
1165 }
1166
onHotplugConnect(hal::HWDisplayId hwcDisplayId)1167 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
1168 hal::HWDisplayId hwcDisplayId) {
1169 std::optional<DisplayIdentificationInfo> info;
1170 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
1171 info = DisplayIdentificationInfo{.id = *displayId,
1172 .name = std::string(),
1173 .deviceProductInfo = std::nullopt};
1174 if (mUpdateDeviceProductInfoOnHotplugReconnect) {
1175 uint8_t port;
1176 DisplayIdentificationData data;
1177 getDisplayIdentificationData(hwcDisplayId, &port, &data);
1178 if (auto newInfo = parseDisplayIdentificationData(port, data)) {
1179 info->deviceProductInfo = std::move(newInfo->deviceProductInfo);
1180 info->preferredDetailedTimingDescriptor =
1181 std::move(newInfo->preferredDetailedTimingDescriptor);
1182 } else {
1183 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
1184 }
1185 }
1186 } else {
1187 uint8_t port;
1188 DisplayIdentificationData data;
1189 const bool hasDisplayIdentificationData =
1190 getDisplayIdentificationData(hwcDisplayId, &port, &data);
1191 if (mPhysicalDisplayIdMap.empty()) {
1192 mHasMultiDisplaySupport = hasDisplayIdentificationData;
1193 ALOGI("Switching to %s multi-display mode",
1194 mHasMultiDisplaySupport ? "generalized" : "legacy");
1195 }
1196
1197 if (shouldIgnoreHotplugConnect(hwcDisplayId, port, hasDisplayIdentificationData)) {
1198 return {};
1199 }
1200
1201 info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
1202 const bool isPrimary = !mPrimaryHwcDisplayId;
1203 if (mHasMultiDisplaySupport) {
1204 if (const auto info = parseDisplayIdentificationData(port, data)) {
1205 return *info;
1206 }
1207 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
1208 } else {
1209 ALOGW_IF(hasDisplayIdentificationData,
1210 "Ignoring identification data for display %" PRIu64, hwcDisplayId);
1211 port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
1212 }
1213
1214 return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
1215 .name = isPrimary ? "Primary display"
1216 : "Secondary display",
1217 .port = port,
1218 .deviceProductInfo = std::nullopt};
1219 }();
1220
1221 mComposer->onHotplugConnect(hwcDisplayId);
1222 }
1223
1224 if (!isConnected(info->id)) {
1225 std::optional<ui::Size> size = std::nullopt;
1226 if (info->preferredDetailedTimingDescriptor) {
1227 size = info->preferredDetailedTimingDescriptor->physicalSizeInMm;
1228 }
1229 allocatePhysicalDisplay(hwcDisplayId, info->id, info->port, size);
1230 }
1231 return info;
1232 }
1233
onHotplugDisconnect(hal::HWDisplayId hwcDisplayId)1234 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
1235 hal::HWDisplayId hwcDisplayId) {
1236 LOG_ALWAYS_FATAL_IF(hwcDisplayId == mPrimaryHwcDisplayId,
1237 "Primary display cannot be disconnected.");
1238
1239 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
1240 if (!displayId) {
1241 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
1242 return {};
1243 }
1244
1245 if (!isConnected(*displayId)) {
1246 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Already disconnected");
1247 return {};
1248 }
1249
1250 // The display will later be destroyed by a call to HWComposer::disconnectDisplay. For now, mark
1251 // it as disconnected.
1252 mDisplayData.at(*displayId).hwcDisplay->setConnected(false);
1253 mComposer->onHotplugDisconnect(hwcDisplayId);
1254 return DisplayIdentificationInfo{.id = *displayId};
1255 }
1256
onHotplugLinkTrainingFailure(hal::HWDisplayId hwcDisplayId)1257 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugLinkTrainingFailure(
1258 hal::HWDisplayId hwcDisplayId) {
1259 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
1260 if (!displayId) {
1261 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
1262 return {};
1263 }
1264 return DisplayIdentificationInfo{.id = *displayId};
1265 }
1266
loadCapabilities()1267 void HWComposer::loadCapabilities() {
1268 static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
1269 auto capabilities = mComposer->getCapabilities();
1270 for (auto capability : capabilities) {
1271 mCapabilities.emplace(capability);
1272 }
1273 }
1274
loadOverlayProperties()1275 void HWComposer::loadOverlayProperties() {
1276 mComposer->getOverlaySupport(&mOverlayProperties);
1277 }
1278
loadHdrConversionCapabilities()1279 void HWComposer::loadHdrConversionCapabilities() {
1280 const auto error = mComposer->getHdrConversionCapabilities(&mHdrConversionCapabilities);
1281 if (error != hal::Error::NONE) {
1282 ALOGE("Error in fetching HDR conversion capabilities %s", to_string(error).c_str());
1283 mHdrConversionCapabilities = {};
1284 }
1285 }
1286
setIdleTimerEnabled(PhysicalDisplayId displayId,std::chrono::milliseconds timeout)1287 status_t HWComposer::setIdleTimerEnabled(PhysicalDisplayId displayId,
1288 std::chrono::milliseconds timeout) {
1289 SFTRACE_CALL();
1290 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1291 const auto error = mDisplayData[displayId].hwcDisplay->setIdleTimerEnabled(timeout);
1292 if (error == hal::Error::UNSUPPORTED) {
1293 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1294 }
1295 if (error == hal::Error::BAD_PARAMETER) {
1296 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1297 }
1298 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1299 return NO_ERROR;
1300 }
1301
hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) const1302 bool HWComposer::hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) const {
1303 RETURN_IF_INVALID_DISPLAY(displayId, false);
1304 return mDisplayData.at(displayId).hwcDisplay->hasDisplayIdleTimerCapability();
1305 }
1306
getPhysicalDisplayOrientation(PhysicalDisplayId displayId) const1307 Hwc2::AidlTransform HWComposer::getPhysicalDisplayOrientation(PhysicalDisplayId displayId) const {
1308 SFTRACE_CALL();
1309 RETURN_IF_INVALID_DISPLAY(displayId, Hwc2::AidlTransform::NONE);
1310 Hwc2::AidlTransform outTransform;
1311 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
1312 const auto error = hwcDisplay->getPhysicalDisplayOrientation(&outTransform);
1313 RETURN_IF_HWC_ERROR(error, displayId, Hwc2::AidlTransform::NONE);
1314 return outTransform;
1315 }
1316
loadLayerMetadataSupport()1317 void HWComposer::loadLayerMetadataSupport() {
1318 mSupportedLayerGenericMetadata.clear();
1319
1320 std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo;
1321 const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo);
1322 if (error != hardware::graphics::composer::V2_4::Error::NONE) {
1323 if (error != hardware::graphics::composer::V2_4::Error::UNSUPPORTED) {
1324 ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
1325 toString(error).c_str(), static_cast<int32_t>(error));
1326 }
1327 return;
1328 }
1329
1330 for (const auto& [name, mandatory] : supportedMetadataKeyInfo) {
1331 mSupportedLayerGenericMetadata.emplace(name, mandatory);
1332 }
1333 }
1334
1335 } // namespace impl
1336 } // namespace android
1337
1338 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1339 #pragma clang diagnostic pop // ignored "-Wconversion"
1340