blob: 55ccdefa7a8cc3ad29b4856ca5a8116fc1fbc4f3 [file] [log] [blame]
Mathias Agopiana350ff92010-08-10 17:14:02 -07001/*
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
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
ramindanic67d22c2023-11-28 14:58:47 -080018#include <chrono>
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080019#pragma clang diagnostic push
20#pragma clang diagnostic ignored "-Wconversion"
21
Dan Stoza9e56aa02015-11-02 13:00:03 -080022// #define LOG_NDEBUG 0
23
24#undef LOG_TAG
25#define LOG_TAG "HWComposer"
Mathias Agopian2965b262012-04-08 15:13:32 -070026#define ATRACE_TAG ATRACE_TAG_GRAPHICS
27
Lloyd Pique66d68602019-02-13 14:23:31 -080028#include "HWComposer.h"
29
Manasi Navarefc2a4a72024-11-12 23:59:21 +000030#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
Marin Shalamanovf8c63722020-10-06 13:11:21 +020031#include <android-base/properties.h>
Vishnu Nairbe0ad902024-06-27 23:38:43 +000032#include <common/trace.h>
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080033#include <compositionengine/Output.h>
34#include <compositionengine/OutputLayer.h>
35#include <compositionengine/impl/OutputLayerCompositionState.h>
Leon Scroggins III959a7ff2023-02-07 11:24:25 -050036#include <ftl/concat.h>
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080037#include <log/log.h>
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070038#include <ui/DebugUtils.h>
Mathias Agopian921e6ac2012-07-23 23:11:29 -070039#include <ui/GraphicBuffer.h>
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080040#include <utils/Errors.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070041
Lloyd Pique66d68602019-02-13 14:23:31 -080042#include "../Layer.h" // needed only for debugging
Marin Shalamanovf8c63722020-10-06 13:11:21 +020043#include "../SurfaceFlingerProperties.h"
Lloyd Pique66d68602019-02-13 14:23:31 -080044#include "ComposerHal.h"
45#include "HWC2.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070046
Dominik Laskowskic1f18f62018-06-13 15:17:55 -070047#define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
48 ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
49
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070050#define LOG_DISPLAY_ERROR(displayId, msg) \
Dominik Laskowski34157762018-10-31 13:07:19 -070051 ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg)
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070052
Dominik Laskowski34157762018-10-31 13:07:19 -070053#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))
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070056
57#define RETURN_IF_INVALID_DISPLAY(displayId, ...) \
58 do { \
Dominik Laskowski075d3172018-05-24 15:50:06 -070059 if (mDisplayData.count(displayId) == 0) { \
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070060 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 { \
Peiyong Line9d809e2020-04-14 13:10:48 -070067 if (error != hal::Error::NONE) { \
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070068 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
Kriti Dang674b9372022-11-18 10:58:44 +010076using aidl::android::hardware::graphics::common::HdrConversionCapability;
77using aidl::android::hardware::graphics::common::HdrConversionStrategy;
Ady Abrahamde549d42022-01-26 19:19:17 -080078using aidl::android::hardware::graphics::composer3::Capability;
79using aidl::android::hardware::graphics::composer3::DisplayCapability;
Lucas Berthou8d0a0c42024-08-27 14:32:31 +000080using aidl::android::hardware::graphics::composer3::DisplayConfiguration;
ramindani355fca82023-12-18 12:07:34 -080081using namespace std::string_literals;
Peiyong Line9d809e2020-04-14 13:10:48 -070082
Marin Shalamanov6e840172020-12-14 22:13:28 +010083namespace android {
Peiyong Linbdd08cc2019-12-17 21:35:14 -080084
Lloyd Pique441d5042018-10-18 16:49:51 -070085HWComposer::~HWComposer() = default;
86
87namespace impl {
88
Marin Shalamanovf8c63722020-10-06 13:11:21 +020089HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
90 : mComposer(std::move(composer)),
Dominik Laskowski13948602021-03-08 20:48:28 -080091 mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))),
Marin Shalamanovf8c63722020-10-06 13:11:21 +020092 mUpdateDeviceProductInfoOnHotplugReconnect(
ramindani355fca82023-12-18 12:07:34 -080093 sysprop::update_device_product_info_on_hotplug_reconnect(false)),
ramindanid2dc07a2024-02-16 16:34:03 -080094 mEnableVrrTimeout(base::GetBoolProperty("debug.sf.vrr_timeout_hint_enabled"s, true)) {}
Peiyong Linbdd08cc2019-12-17 21:35:14 -080095
96HWComposer::HWComposer(const std::string& composerServiceName)
Ady Abraham9fc28052021-10-14 17:21:38 -070097 : HWComposer(Hwc2::Composer::create(composerServiceName)) {}
Mathias Agopianbef42c52013-08-21 17:45:46 -070098
Dominik Laskowskib04f98a2018-11-07 21:07:16 -080099HWComposer::~HWComposer() {
100 mDisplayData.clear();
101}
Dan Stoza9e56aa02015-11-02 13:00:03 -0800102
Yichi Chen3401b562022-01-17 15:42:35 +0800103void HWComposer::setCallback(HWC2::ComposerCallback& callback) {
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800104 loadCapabilities();
105 loadLayerMetadataSupport();
Sally Qibb866c12022-10-17 11:31:20 -0700106 loadOverlayProperties();
Kriti Dang674b9372022-11-18 10:58:44 +0100107 loadHdrConversionCapabilities();
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800108
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800109 if (mRegisteredCallback) {
110 ALOGW("Callback already registered. Ignored extra registration attempt.");
111 return;
112 }
113 mRegisteredCallback = true;
Dominik Laskowskiebc8d3a2021-04-16 23:18:31 -0700114
Yichi Chen3401b562022-01-17 15:42:35 +0800115 mComposer->registerCallback(callback);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800116}
117
Peiyong Line9d809e2020-04-14 13:10:48 -0700118bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700119 DisplayIdentificationData* outData) const {
Peiyong Line9d809e2020-04-14 13:10:48 -0700120 const auto error = static_cast<hal::Error>(
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800121 mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
Peiyong Line9d809e2020-04-14 13:10:48 -0700122 if (error != hal::Error::NONE) {
123 if (error != hal::Error::UNSUPPORTED) {
Chia-I Wud0aff9d2018-06-21 13:39:09 +0800124 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
125 }
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700126 return false;
127 }
128 return true;
129}
130
Ady Abrahamde549d42022-01-26 19:19:17 -0800131bool HWComposer::hasCapability(Capability capability) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800132 return mCapabilities.count(capability) > 0;
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700133}
134
Ady Abrahamde549d42022-01-26 19:19:17 -0800135bool HWComposer::hasDisplayCapability(HalDisplayId displayId, DisplayCapability capability) const {
Dominik Laskowski1162e472020-04-02 19:02:47 -0700136 RETURN_IF_INVALID_DISPLAY(displayId, false);
Ady Abraham27fbcc72021-09-20 14:54:57 -0700137 return mDisplayData.at(displayId).hwcDisplay->hasCapability(capability);
Peiyong Lined531a32018-10-26 18:27:56 -0700138}
139
Peiyong Line9d809e2020-04-14 13:10:48 -0700140std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
141 hal::Connection connection) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100142 switch (connection) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700143 case hal::Connection::CONNECTED:
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100144 return onHotplugConnect(hwcDisplayId);
Peiyong Line9d809e2020-04-14 13:10:48 -0700145 case hal::Connection::DISCONNECTED:
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100146 return onHotplugDisconnect(hwcDisplayId);
Peiyong Line9d809e2020-04-14 13:10:48 -0700147 case hal::Connection::INVALID:
Dominik Laskowski075d3172018-05-24 15:50:06 -0700148 return {};
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700149 }
Andy McFaddenb0d1dd32012-09-10 14:08:09 -0700150}
151
Marin Shalamanovf8c63722020-10-06 13:11:21 +0200152bool HWComposer::updatesDeviceProductInfoOnHotplugReconnect() const {
153 return mUpdateDeviceProductInfoOnHotplugReconnect;
154}
155
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500156std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId,
157 nsecs_t timestamp) {
158 const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId);
159 if (!displayIdOpt) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700160 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500161 return {};
Jesse Hall1bd20e02012-08-29 10:47:52 -0700162 }
Jesse Hall1bd20e02012-08-29 10:47:52 -0700163
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500164 RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {});
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700165
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500166 auto& displayData = mDisplayData[*displayIdOpt];
Jesse Hall1bd20e02012-08-29 10:47:52 -0700167
Dan Stoza9e56aa02015-11-02 13:00:03 -0800168 {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800169 // 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.
Dominik Laskowskidc2bb802022-09-28 16:02:59 -0400173 if (timestamp == displayData.lastPresentTimestamp) {
Dominik Laskowski34157762018-10-31 13:07:19 -0700174 ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500175 to_string(*displayIdOpt).c_str(), timestamp);
176 return {};
Dan Stoza9e56aa02015-11-02 13:00:03 -0800177 }
178
Dominik Laskowskidc2bb802022-09-28 16:02:59 -0400179 displayData.lastPresentTimestamp = timestamp;
Jesse Hall1c569c42013-04-05 13:44:52 -0700180 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800181
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000182 SFTRACE_INT(ftl::Concat("HW_VSYNC_", displayIdOpt->value).c_str(),
183 displayData.vsyncTraceToggle);
Dominik Laskowski1af47932018-11-12 10:20:46 -0800184 displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800185
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500186 return displayIdOpt;
Jesse Hall1c569c42013-04-05 13:44:52 -0700187}
188
Dominik Laskowski13948602021-03-08 20:48:28 -0800189size_t HWComposer::getMaxVirtualDisplayCount() const {
190 return mComposer->getMaxVirtualDisplayCount();
191}
192
193size_t HWComposer::getMaxVirtualDisplayDimension() const {
194 return mMaxVirtualDisplayDimension;
195}
196
197bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size resolution,
Dominik Laskowski263eec42021-07-21 23:13:24 -0700198 ui::PixelFormat* format) {
Dominik Laskowski13948602021-03-08 20:48:28 -0800199 if (!resolution.isValid()) {
200 ALOGE("%s: Invalid resolution %dx%d", __func__, resolution.width, resolution.height);
201 return false;
Fabien Sanglarde29055f2017-03-08 11:36:46 -0800202 }
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200203
Dominik Laskowski13948602021-03-08 20:48:28 -0800204 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;
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200212 }
213
Dominik Laskowski13948602021-03-08 20:48:28 -0800214 hal::HWDisplayId hwcDisplayId;
Peiyong Line9d809e2020-04-14 13:10:48 -0700215 const auto error = static_cast<hal::Error>(
Dominik Laskowski263eec42021-07-21 23:13:24 -0700216 mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
Dominik Laskowski13948602021-03-08 20:48:28 -0800217 RETURN_IF_HWC_ERROR_FOR("createVirtualDisplay", error, displayId, false);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800218
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800219 auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
Peiyong Line9d809e2020-04-14 13:10:48 -0700220 hwcDisplayId, hal::DisplayType::VIRTUAL);
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800221 display->setConnected(true);
Dominik Laskowski13948602021-03-08 20:48:28 -0800222 auto& displayData = mDisplayData[displayId];
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800223 displayData.hwcDisplay = std::move(display);
Dominik Laskowski13948602021-03-08 20:48:28 -0800224 return true;
Mathias Agopiane60b0682012-08-21 23:34:09 -0700225}
226
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000227void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, PhysicalDisplayId displayId,
228 std::optional<ui::Size> physicalSize) {
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100229 mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
230
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700231 if (!mPrimaryHwcDisplayId) {
232 mPrimaryHwcDisplayId = hwcDisplayId;
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100233 }
234
235 auto& displayData = mDisplayData[displayId];
236 auto newDisplay =
237 std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
Peiyong Line9d809e2020-04-14 13:10:48 -0700238 hal::DisplayType::PHYSICAL);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100239 newDisplay->setConnected(true);
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000240 newDisplay->setPhysicalSizeInMm(physicalSize);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100241 displayData.hwcDisplay = std::move(newDisplay);
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100242}
243
244int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
Marin Shalamanov045b7002021-01-07 16:56:24 +0100245 hal::Attribute attribute) const {
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100246 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
Lloyd Pique1b33fc32021-05-07 14:36:58 -0700254std::shared_ptr<HWC2::Layer> HWComposer::createLayer(HalDisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700255 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
256
Lloyd Pique1b33fc32021-05-07 14:36:58 -0700257 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();
Steven Thomas94e35b92017-07-26 18:48:28 -0700263}
264
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200265bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
Dominik Laskowskif2ddca62022-08-17 12:08:07 -0700266 return mDisplayData.count(displayId) && mDisplayData.at(displayId).hwcDisplay->isConnected();
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700267}
268
ramindani263a3f12023-07-18 20:44:49 -0700269std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId,
270 int32_t maxFrameIntervalNs) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700271 RETURN_IF_INVALID_DISPLAY(displayId, {});
272
Marin Shalamanov045b7002021-01-07 16:56:24 +0100273 const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
ramindani0cd1d8d2023-06-13 13:43:23 -0700274
ramindani19919ff2023-12-07 11:27:06 -0800275 if (mComposer->isVrrSupported()) {
ramindani263a3f12023-07-18 20:44:49 -0700276 return getModesFromDisplayConfigurations(hwcDisplayId, maxFrameIntervalNs);
ramindani0cd1d8d2023-06-13 13:43:23 -0700277 }
278
279 return getModesFromLegacyDisplayConfigs(hwcDisplayId);
280}
281
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000282DisplayConfiguration::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
301DisplayConfiguration::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.
Lucas Berthou685c3522024-09-16 14:39:05 +0000309 if (estimatedDpi.x == -1 || estimatedDpi.y == -1) {
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000310 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
ramindani0cd1d8d2023-06-13 13:43:23 -0700323std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromDisplayConfigurations(
ramindani263a3f12023-07-18 20:44:49 -0700324 uint64_t hwcDisplayId, int32_t maxFrameIntervalNs) const {
ramindani0cd1d8d2023-06-13 13:43:23 -0700325 std::vector<hal::DisplayConfiguration> configs;
ramindani263a3f12023-07-18 20:44:49 -0700326 auto error = static_cast<hal::Error>(
327 mComposer->getDisplayConfigurations(hwcDisplayId, maxFrameIntervalNs, &configs));
ramindani0cd1d8d2023-06-13 13:43:23 -0700328 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) {
ramindania04b8a52023-08-07 18:49:47 -0700334 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,
Sasha McIntoshf08ed642024-10-24 15:43:07 -0400339 .vrrConfig = config.vrrConfig,
340 .hdrOutputType = config.hdrOutputType};
ramindani0cd1d8d2023-06-13 13:43:23 -0700341
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000342 const DisplayConfiguration::Dpi estimatedDPI =
343 getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
ramindani0cd1d8d2023-06-13 13:43:23 -0700344 if (config.dpi) {
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000345 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;
ramindani0cd1d8d2023-06-13 13:43:23 -0700352 }
353
ramindani355fca82023-12-18 12:07:34 -0800354 if (!mEnableVrrTimeout) {
355 hwcMode.vrrConfig->notifyExpectedPresentConfig = {};
356 }
357
ramindani0cd1d8d2023-06-13 13:43:23 -0700358 modes.push_back(hwcMode);
359 }
360
361 return modes;
362}
363
364std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromLegacyDisplayConfigs(
365 uint64_t hwcDisplayId) const {
Marin Shalamanov045b7002021-01-07 16:56:24 +0100366 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) {
ramindani0cd1d8d2023-06-13 13:43:23 -0700373 auto hwcMode = HWCDisplayMode{
Marin Shalamanov045b7002021-01-07 16:56:24 +0100374 .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),
Marin Shalamanov045b7002021-01-07 16:56:24 +0100378 .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
ramindani0cd1d8d2023-06-13 13:43:23 -0700379 };
Marin Shalamanov045b7002021-01-07 16:56:24 +0100380
ramindani0cd1d8d2023-06-13 13:43:23 -0700381 const int32_t dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X);
382 const int32_t dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y);
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000383 const DisplayConfiguration::Dpi hwcDpi =
Lucas Berthouae3611d2024-10-16 19:58:52 +0000384 DisplayConfiguration::Dpi{dpiX == -1 ? dpiX : dpiX / 1000.f,
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000385 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;
ramindani0cd1d8d2023-06-13 13:43:23 -0700391
392 modes.push_back(hwcMode);
393 }
Marin Shalamanov045b7002021-01-07 16:56:24 +0100394 return modes;
Mathias Agopianda27af92012-09-13 18:17:13 -0700395}
396
Dominik Laskowskid940a012024-01-28 13:25:44 -0500397ftl::Expected<hal::HWConfigId, status_t> HWComposer::getActiveMode(
398 PhysicalDisplayId displayId) const {
399 RETURN_IF_INVALID_DISPLAY(displayId, ftl::Unexpected(BAD_INDEX));
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100400 const auto hwcId = *fromPhysicalDisplayId(displayId);
Dominik Laskowskie2c5b0a2022-08-10 14:53:53 -0700401
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100402 hal::HWConfigId configId;
Dominik Laskowskie2c5b0a2022-08-10 14:53:53 -0700403 const auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
Dominik Laskowskid940a012024-01-28 13:25:44 -0500404 if (error == hal::Error::BAD_CONFIG) {
405 return ftl::Unexpected(NO_INIT);
406 }
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100407
Dominik Laskowskid940a012024-01-28 13:25:44 -0500408 RETURN_IF_HWC_ERROR_FOR("getActiveConfig", error, displayId, ftl::Unexpected(UNKNOWN_ERROR));
Marin Shalamanov045b7002021-01-07 16:56:24 +0100409 return configId;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700410}
411
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800412// Composer 2.4
413
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100414ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
415 RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal);
Dominik Laskowski55c85402020-01-21 16:25:47 -0800416 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
417
Dominik Laskowski969cdcb2024-02-08 16:35:29 -0500418 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 }
Dominik Laskowski55c85402020-01-21 16:25:47 -0800425}
426
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200427bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const {
Dominik Laskowski55c85402020-01-21 16:25:47 -0800428 RETURN_IF_INVALID_DISPLAY(displayId, false);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800429 return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
430}
431
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500432ftl::Expected<nsecs_t, status_t> HWComposer::getDisplayVsyncPeriod(
433 PhysicalDisplayId displayId) const {
434 RETURN_IF_INVALID_DISPLAY(displayId, ftl::Unexpected(BAD_INDEX));
Dominik Laskowski55c85402020-01-21 16:25:47 -0800435
Marin Shalamanov045b7002021-01-07 16:56:24 +0100436 if (!isVsyncPeriodSwitchSupported(displayId)) {
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500437 return ftl::Unexpected(INVALID_OPERATION);
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700438 }
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500439
Marin Shalamanov045b7002021-01-07 16:56:24 +0100440 const auto hwcId = *fromPhysicalDisplayId(displayId);
441 Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500442 const auto error =
Marin Shalamanov045b7002021-01-07 16:56:24 +0100443 static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500444 RETURN_IF_HWC_ERROR(error, displayId, ftl::Unexpected(UNKNOWN_ERROR));
445 return static_cast<nsecs_t>(vsyncPeriodNanos);
Lloyd Pique3c085a02018-05-09 19:38:32 -0700446}
447
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200448std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700449 RETURN_IF_INVALID_DISPLAY(displayId, {});
450
Peiyong Linfd997e02018-03-28 15:29:00 -0700451 std::vector<ui::ColorMode> modes;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700452 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700453 RETURN_IF_HWC_ERROR(error, displayId, {});
Courtney Goeltzenleuchterfad9d8c2016-06-23 11:49:50 -0600454 return modes;
455}
456
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200457status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700458 ui::RenderIntent renderIntent) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700459 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Michael Wright28f24d02016-07-12 13:30:53 -0700460
461 auto& displayData = mDisplayData[displayId];
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700462 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700463 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
464 decodeRenderIntent(renderIntent) + ")")
465 .c_str(),
466 error, displayId, UNKNOWN_ERROR);
Michael Wright28f24d02016-07-12 13:30:53 -0700467
468 return NO_ERROR;
469}
470
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200471void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700472 RETURN_IF_INVALID_DISPLAY(displayId);
473 auto& displayData = mDisplayData[displayId];
474
Dan Stoza9e56aa02015-11-02 13:00:03 -0800475 // 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.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800479 std::lock_guard lock(displayData.vsyncEnabledLock);
480 if (enabled == displayData.vsyncEnabled) {
481 return;
Colin Cross10fbdb62012-07-12 17:56:34 -0700482 }
Dominik Laskowski1af47932018-11-12 10:20:46 -0800483
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000484 SFTRACE_CALL();
Dominik Laskowski1af47932018-11-12 10:20:46 -0800485 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
486 RETURN_IF_HWC_ERROR(error, displayId);
487
488 displayData.vsyncEnabled = enabled;
489
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000490 SFTRACE_INT(ftl::Concat("HW_VSYNC_ON_", displayId.value).c_str(),
491 enabled == hal::Vsync::ENABLE ? 1 : 0);
Colin Cross10fbdb62012-07-12 17:56:34 -0700492}
493
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200494status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700495 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
Alec Mourif97df4d2023-09-06 02:10:05 +0000496 ui::Dataspace dataspace, float hdrSdrRatio) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700497 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Jesse Hall851cfe82013-03-20 13:44:00 -0700498
Dominik Laskowski34157762018-10-31 13:07:19 -0700499 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
Dan Stoza9e56aa02015-11-02 13:00:03 -0800500 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Alec Mourif97df4d2023-09-06 02:10:05 +0000501 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace, hdrSdrRatio);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700502 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
Jesse Hall851cfe82013-03-20 13:44:00 -0700503 return NO_ERROR;
504}
505
Lloyd Pique66d68602019-02-13 14:23:31 -0800506status_t HWComposer::getDeviceCompositionChanges(
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200507 HalDisplayId displayId, bool frameUsesClientComposition,
Ady Abrahamf1db8032023-03-24 17:52:34 -0700508 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime,
ramindani4aac32c2023-10-30 14:13:30 -0700509 nsecs_t expectedPresentTime, Fps frameInterval,
Lloyd Pique66d68602019-02-13 14:23:31 -0800510 std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000511 SFTRACE_CALL();
Dan Stoza9e56aa02015-11-02 13:00:03 -0800512
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700513 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800514
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;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700523
Peiyong Line9d809e2020-04-14 13:10:48 -0700524 hal::Error error = hal::Error::NONE;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700525
Ady Abrahamec7aa8a2021-06-28 12:37:09 -0700526 // 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
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700530 // client target buffer.
Ady Abraham43065bd2021-12-10 17:22:15 -0800531 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
Ady Abrahamf1db8032023-03-24 17:52:34 -0700539 if (!earliestPresentTime) {
Ady Abraham43065bd2021-12-10 17:22:15 -0800540 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.
Ady Abrahamf1db8032023-03-24 17:52:34 -0700545 return std::chrono::steady_clock::now() >= *earliestPresentTime;
Ady Abraham43065bd2021-12-10 17:22:15 -0800546 }();
547
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700548 displayData.validateWasSkipped = false;
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000549 SFTRACE_FORMAT("NextFrameInterval %d_Hz", frameInterval.getIntValue());
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700550 if (canSkipValidate) {
Leon Scroggins IIIabc2c452023-11-08 17:04:51 -0500551 sp<Fence> outPresentFence = Fence::NO_FENCE;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700552 uint32_t state = UINT32_MAX;
ramindani4aac32c2023-10-30 14:13:30 -0700553 error = hwcDisplay->presentOrValidate(expectedPresentTime, frameInterval.getPeriodNsecs(),
554 &numTypes, &numRequests, &outPresentFence, &state);
Peiyong Line9d809e2020-04-14 13:10:48 -0700555 if (!hasChangesError(error)) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700556 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700557 }
558 if (state == 1) { //Present Succeeded.
Steven Thomas94e35b92017-07-26 18:48:28 -0700559 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700560 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 {
ramindani09acbb82023-11-03 09:02:38 -0700569 error = hwcDisplay->validate(expectedPresentTime, frameInterval.getPeriodNsecs(), &numTypes,
570 &numRequests);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700571 }
572 ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
Peiyong Line9d809e2020-04-14 13:10:48 -0700573 if (!hasChangesError(error)) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700574 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800575 }
576
Lloyd Pique66d68602019-02-13 14:23:31 -0800577 android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800578 changedTypes.reserve(numTypes);
579 error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700580 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800581
Peiyong Line9d809e2020-04-14 13:10:48 -0700582 auto displayRequests = static_cast<hal::DisplayRequest>(0);
Lloyd Pique66d68602019-02-13 14:23:31 -0800583 android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800584 layerRequests.reserve(numRequests);
Lloyd Pique66d68602019-02-13 14:23:31 -0800585 error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700586 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800587
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700588 DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
Alec Mouri85065692022-03-18 00:58:26 +0000589 error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
Sally Qi11dcd582024-08-16 18:11:27 -0700590 RETURN_IF_HWC_ERROR_FOR("getClientTargetProperty", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800591
Sally Qi95f669a2024-08-27 11:31:42 -0700592 DeviceRequestedChanges::LayerLuts layerLuts;
593 error = hwcDisplay->getRequestedLuts(&layerLuts, mLutFileDescriptorMapper);
594 RETURN_IF_HWC_ERROR_FOR("getRequestedLuts", error, displayId, BAD_INDEX);
595
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700596 outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
597 std::move(layerRequests),
Sally Qi95f669a2024-08-27 11:31:42 -0700598 std::move(clientTargetProperty),
599 std::move(layerLuts)});
Dan Stoza9e56aa02015-11-02 13:00:03 -0800600 error = hwcDisplay->acceptChanges();
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700601 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800602
603 return NO_ERROR;
604}
605
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200606sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700607 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700608 return mDisplayData.at(displayId).lastPresentFence;
Jesse Hall851cfe82013-03-20 13:44:00 -0700609}
610
Dominik Laskowskidc2bb802022-09-28 16:02:59 -0400611nsecs_t HWComposer::getPresentTimestamp(PhysicalDisplayId displayId) const {
612 RETURN_IF_INVALID_DISPLAY(displayId, 0);
613 return mDisplayData.at(displayId).lastPresentTimestamp;
614}
615
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200616sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700617 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Tim Murray2d3f8b82019-12-04 16:24:17 -0800618 const auto& displayFences = mDisplayData.at(displayId).releaseFences;
619 auto fence = displayFences.find(layer);
620 if (fence == displayFences.end()) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800621 ALOGV("getLayerReleaseFence: Release fence not found");
622 return Fence::NO_FENCE;
Riley Andrews03414a12014-07-01 14:22:59 -0700623 }
Tim Murray2d3f8b82019-12-04 16:24:17 -0800624 return fence->second;
Riley Andrews03414a12014-07-01 14:22:59 -0700625}
626
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700627status_t HWComposer::presentAndGetReleaseFences(
Ady Abrahamf1db8032023-03-24 17:52:34 -0700628 HalDisplayId displayId,
629 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000630 SFTRACE_CALL();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700631
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700632 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Pablo Ceballosd814cf22015-09-11 14:37:39 -0700633
Dan Stoza9e56aa02015-11-02 13:00:03 -0800634 auto& displayData = mDisplayData[displayId];
635 auto& hwcDisplay = displayData.hwcDisplay;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700636
637 if (displayData.validateWasSkipped) {
Chia-I Wuae5a6b82017-10-10 09:09:22 -0700638 // explicitly flush all pending commands
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -0400639 auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800640 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700641 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700642 return NO_ERROR;
643 }
644
Ady Abrahamf1db8032023-03-24 17:52:34 -0700645 if (earliestPresentTime) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000646 SFTRACE_NAME("wait for earliest present time");
Ady Abrahamf1db8032023-03-24 17:52:34 -0700647 std::this_thread::sleep_until(*earliestPresentTime);
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700648 }
649
Fabien Sanglard11d0fc32016-12-01 15:43:01 -0800650 auto error = hwcDisplay->present(&displayData.lastPresentFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700651 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700652
Steven Thomas94e35b92017-07-26 18:48:28 -0700653 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800654 error = hwcDisplay->getReleaseFences(&releaseFences);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700655 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800656
657 displayData.releaseFences = std::move(releaseFences);
658
659 return NO_ERROR;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700660}
661
Leon Scroggins IIIa3ba7fa2024-05-22 16:34:52 -0400662status_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
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200669status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700670 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
671
Peiyong Line9d809e2020-04-14 13:10:48 -0700672 if (mode == hal::PowerMode::OFF) {
673 setVsyncEnabled(displayId, hal::Vsync::DISABLE);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800674 }
675
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700676 const auto& displayData = mDisplayData[displayId];
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700677 auto& hwcDisplay = displayData.hwcDisplay;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800678 switch (mode) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700679 case hal::PowerMode::OFF:
680 case hal::PowerMode::ON:
Dan Stoza9e56aa02015-11-02 13:00:03 -0800681 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
682 {
683 auto error = hwcDisplay->setPowerMode(mode);
Peiyong Line9d809e2020-04-14 13:10:48 -0700684 if (error != hal::Error::NONE) {
685 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
686 displayId);
Peiyong Lin306e4992018-05-07 16:18:22 -0700687 }
Mathias Agopianda27af92012-09-13 18:17:13 -0700688 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800689 break;
Peiyong Line9d809e2020-04-14 13:10:48 -0700690 case hal::PowerMode::DOZE:
691 case hal::PowerMode::DOZE_SUSPEND:
Dan Stoza9e56aa02015-11-02 13:00:03 -0800692 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
693 {
694 bool supportsDoze = false;
Leon Scroggins III689c80f2023-06-05 17:49:32 -0400695 const auto queryDozeError = hwcDisplay->supportsDoze(&supportsDoze);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700696
Leon Scroggins III689c80f2023-06-05 17:49:32 -0400697 // 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) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700700 mode = hal::PowerMode::ON;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800701 }
702
Leon Scroggins III689c80f2023-06-05 17:49:32 -0400703 auto error = hwcDisplay->setPowerMode(mode);
Peiyong Line9d809e2020-04-14 13:10:48 -0700704 if (error != hal::Error::NONE) {
705 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
706 displayId);
Leon Scroggins III689c80f2023-06-05 17:49:32 -0400707 // 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 }
Peiyong Lin306e4992018-05-07 16:18:22 -0700718 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800719 }
720 break;
721 default:
722 ALOGV("setPowerMode: Not calling HWC");
723 break;
Mathias Agopianda27af92012-09-13 18:17:13 -0700724 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800725
726 return NO_ERROR;
727}
728
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100729status_t HWComposer::setActiveModeWithConstraints(
Marin Shalamanov12c9e5a2021-01-07 00:25:35 +0100730 PhysicalDisplayId displayId, hal::HWConfigId hwcModeId,
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200731 const hal::VsyncPeriodChangeConstraints& constraints,
Peiyong Line9d809e2020-04-14 13:10:48 -0700732 hal::VsyncPeriodChangeTimeline* outTimeline) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700733 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800734
Marin Shalamanov12c9e5a2021-01-07 00:25:35 +0100735 auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
736 constraints,
737 outTimeline);
Manasi Navarefc2a4a72024-11-12 23:59:21 +0000738 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);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800743 return NO_ERROR;
744}
745
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200746status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700747 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700748
749 auto& displayData = mDisplayData[displayId];
Ady Abrahamdc011a92021-12-21 14:06:44 -0800750 auto error = displayData.hwcDisplay->setColorTransform(transform);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700751 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700752 return NO_ERROR;
753}
754
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200755void HWComposer::disconnectDisplay(HalDisplayId displayId) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700756 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800757 auto& displayData = mDisplayData[displayId];
Dominik Laskowski7e045462018-05-30 13:02:02 -0700758 const auto hwcDisplayId = displayData.hwcDisplay->getId();
Dominik Laskowski075d3172018-05-24 15:50:06 -0700759
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800760 mPhysicalDisplayIdMap.erase(hwcDisplayId);
761 mDisplayData.erase(displayId);
Marin Shalamanov8b196592021-08-09 16:24:42 +0200762
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 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800769}
770
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200771status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700772 const sp<GraphicBuffer>& buffer) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700773 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700774 const auto& displayData = mDisplayData[displayId];
Dan Stoza9e56aa02015-11-02 13:00:03 -0800775
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700776 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700777 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800778 return NO_ERROR;
779}
780
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200781void HWComposer::clearReleaseFences(HalDisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700782 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800783 mDisplayData[displayId].releaseFences.clear();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700784}
785
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200786status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700787 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stozac4f471e2016-03-24 09:31:08 -0700788
789 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Peiyong Lin62665892018-04-16 11:07:44 -0700790 auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700791 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Peiyong Lin62665892018-04-16 11:07:44 -0700792 return NO_ERROR;
Dan Stozac4f471e2016-03-24 09:31:08 -0700793}
794
Sally Qibb866c12022-10-17 11:31:20 -0700795const aidl::android::hardware::graphics::composer3::OverlayProperties&
796HWComposer::getOverlaySupport() const {
797 return mOverlayProperties;
Sally Qi0cbd08b2022-08-17 12:12:28 -0700798}
799
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200800int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700801 RETURN_IF_INVALID_DISPLAY(displayId, 0);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700802 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
Peiyong Lin0ac5f4e2018-04-19 22:06:34 -0700803}
804
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200805std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700806 ui::ColorMode colorMode) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700807 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700808
809 std::vector<ui::RenderIntent> renderIntents;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700810 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700811 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700812 return renderIntents;
813}
814
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200815mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700816 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700817
818 mat4 matrix;
819 auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
820 &matrix);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700821 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700822 return matrix;
823}
824
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200825status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId,
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700826 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);
Peiyong Line9d809e2020-04-14 13:10:48 -0700834 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700835 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
836 return NO_ERROR;
837}
838
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200839status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled,
Kevin DuBois74e53772018-11-19 10:52:38 -0800840 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
Peiyong Line9d809e2020-04-14 13:10:48 -0700847 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);
Kevin DuBois74e53772018-11-19 10:52:38 -0800849 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
850 return NO_ERROR;
851}
852
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200853status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames,
Kevin DuBois1d4249a2018-08-29 10:45:14 -0700854 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
Dominik Laskowskib17c6212022-05-09 09:36:19 -0700863ftl::Future<status_t> HWComposer::setDisplayBrightness(
Alec Mouri4d8a05d2022-03-23 18:14:26 +0000864 PhysicalDisplayId displayId, float brightness, float brightnessNits,
Alec Mouricdf16792021-12-10 13:16:06 -0800865 const Hwc2::Composer::DisplayBrightnessOptions& options) {
Dominik Laskowski4e2b71f2020-11-10 15:05:32 -0800866 RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX));
Dominik Laskowski5690bde2020-04-23 19:04:22 -0700867 auto& display = mDisplayData[displayId].hwcDisplay;
868
Dominik Laskowskib17c6212022-05-09 09:36:19 -0700869 return display->setDisplayBrightness(brightness, brightnessNits, options)
Dominik Laskowski5690bde2020-04-23 19:04:22 -0700870 .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 });
Dan Gittik57e63c52019-01-18 16:37:54 +0000880}
881
Matt Buckley50c44062022-01-17 20:48:10 +0000882bool HWComposer::getValidateSkipped(HalDisplayId displayId) const {
883 if (mDisplayData.count(displayId) == 0) {
884 return false;
885 }
886 return mDisplayData.at(displayId).validateWasSkipped;
887}
888
Kriti Dang7defaf32021-11-15 11:55:43 +0100889status_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
903status_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
Kriti Dang16ca2972022-02-01 20:07:03 +0100916std::optional<hal::HWConfigId> HWComposer::getPreferredBootDisplayMode(
917 PhysicalDisplayId displayId) {
918 RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
919 hal::HWConfigId displayModeId;
Kriti Dang7defaf32021-11-15 11:55:43 +0100920 const auto error =
921 mDisplayData[displayId].hwcDisplay->getPreferredBootDisplayConfig(&displayModeId);
Kriti Dang16ca2972022-02-01 20:07:03 +0100922 if (error != hal::Error::NONE) {
923 LOG_DISPLAY_ERROR(displayId, to_string(error).c_str());
924 return std::nullopt;
Kriti Dang7defaf32021-11-15 11:55:43 +0100925 }
Kriti Dang7defaf32021-11-15 11:55:43 +0100926 return displayModeId;
927}
928
Kriti Dang674b9372022-11-18 10:58:44 +0100929std::vector<HdrConversionCapability> HWComposer::getHdrConversionCapabilities() const {
930 return mHdrConversionCapabilities;
931}
932
Kriti Dangd432bb52023-02-09 18:21:04 +0100933status_t HWComposer::setHdrConversionStrategy(
934 HdrConversionStrategy hdrConversionStrategy,
935 aidl::android::hardware::graphics::common::Hdr* outPreferredHdrOutputType) {
936 const auto error =
937 mComposer->setHdrConversionStrategy(hdrConversionStrategy, outPreferredHdrOutputType);
Kriti Dang674b9372022-11-18 10:58:44 +0100938 if (error != hal::Error::NONE) {
939 ALOGE("Error in setting HDR conversion strategy %s", to_string(error).c_str());
Kriti Dangd432bb52023-02-09 18:21:04 +0100940 return INVALID_OPERATION;
Kriti Dang674b9372022-11-18 10:58:44 +0100941 }
942 return NO_ERROR;
943}
944
ramindanib2158ee2023-02-13 20:29:59 -0800945status_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
ramindanic67d22c2023-11-28 14:58:47 -0800960status_t HWComposer::notifyExpectedPresent(PhysicalDisplayId displayId,
961 TimePoint expectedPresentTime, Fps frameInterval) {
ramindani3acaaf52023-09-25 10:31:27 -0700962 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000963 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())));
ramindanic67d22c2023-11-28 14:58:47 -0800966 const auto error = mComposer->notifyExpectedPresent(mDisplayData[displayId].hwcDisplay->getId(),
ramindanif8c0f102023-10-09 12:42:57 -0700967 expectedPresentTime.ns(),
968 frameInterval.getPeriodNsecs());
ramindani3acaaf52023-09-25 10:31:27 -0700969 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
Leon Scroggins IIIe7c51c62022-02-01 15:53:54 -0500976status_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
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200992status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100993 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
994 const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
Peiyong Line9d809e2020-04-14 13:10:48 -0700995 if (error == hal::Error::UNSUPPORTED) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100996 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
997 }
Peiyong Line9d809e2020-04-14 13:10:48 -0700998 if (error == hal::Error::BAD_PARAMETER) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100999 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1000 }
1001 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1002 return NO_ERROR;
1003}
1004
1005status_t HWComposer::getSupportedContentTypes(
Dominik Laskowski6c7b36e2022-03-03 08:27:58 -08001006 PhysicalDisplayId displayId,
1007 std::vector<hal::ContentType>* outSupportedContentTypes) const {
Galia Peycheva5492cb52019-10-30 14:13:16 +01001008 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dominik Laskowski6c7b36e2022-03-03 08:27:58 -08001009 const auto error = mDisplayData.at(displayId).hwcDisplay->getSupportedContentTypes(
1010 outSupportedContentTypes);
Galia Peycheva5492cb52019-10-30 14:13:16 +01001011
1012 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1013
1014 return NO_ERROR;
1015}
1016
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +02001017status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) {
Galia Peycheva5492cb52019-10-30 14:13:16 +01001018 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1019 const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
Peiyong Line9d809e2020-04-14 13:10:48 -07001020 if (error == hal::Error::UNSUPPORTED) {
Galia Peycheva5492cb52019-10-30 14:13:16 +01001021 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1022 }
Peiyong Line9d809e2020-04-14 13:10:48 -07001023 if (error == hal::Error::BAD_PARAMETER) {
Galia Peycheva5492cb52019-10-30 14:13:16 +01001024 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
Brian Lindahl7a4cb7e2024-10-30 10:42:21 -06001031int32_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
1039status_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
Lloyd Pique4603f3c2020-02-11 12:06:56 -08001049const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
1050 return mSupportedLayerGenericMetadata;
1051}
1052
Sally Qi95f669a2024-08-27 11:31:42 -07001053ftl::SmallMap<HWC2::Layer*, ndk::ScopedFileDescriptor, 20>&
1054HWComposer::getLutFileDescriptorMapper() {
1055 return mLutFileDescriptorMapper;
1056}
1057
Sally Qi254ef492024-04-08 15:01:28 -07001058void 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",
Sally Qi5dfdf142024-04-15 16:50:24 +00001075 decodeStandardOnly(static_cast<uint32_t>(standard)).c_str(),
Sally Qi254ef492024-04-08 15:01:28 -07001076 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
Yiwei Zhang5434a782018-12-05 18:06:32 -08001094void HWComposer::dump(std::string& result) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001095 result.append(mComposer->dumpDebugInfo());
Sally Qi254ef492024-04-08 15:01:28 -07001096 dumpOverlayProperties(result);
Mathias Agopian83727852010-09-23 18:13:21 -07001097}
1098
Marin Shalamanova524a092020-07-27 21:39:55 +02001099std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
1100 hal::HWDisplayId hwcDisplayId) const {
Dominik Laskowski075d3172018-05-24 15:50:06 -07001101 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
1102 it != mPhysicalDisplayIdMap.end()) {
1103 return it->second;
1104 }
1105 return {};
1106}
1107
Marin Shalamanova524a092020-07-27 21:39:55 +02001108std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
1109 PhysicalDisplayId displayId) const {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001110 if (const auto it = mDisplayData.find(displayId); it != mDisplayData.end()) {
Dominik Laskowski075d3172018-05-24 15:50:06 -07001111 return it->second.hwcDisplay->getId();
1112 }
1113 return {};
1114}
1115
Peiyong Line9d809e2020-04-14 13:10:48 -07001116bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001117 bool hasDisplayIdentificationData) const {
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001118 if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
Dominik Laskowski075d3172018-05-24 15:50:06 -07001119 ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
1120 hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001121 return true;
Dominik Laskowski075d3172018-05-24 15:50:06 -07001122 }
1123
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001124 // Legacy mode only supports IDs LEGACY_DISPLAY_TYPE_PRIMARY and LEGACY_DISPLAY_TYPE_EXTERNAL.
1125 if (!mHasMultiDisplaySupport && mPhysicalDisplayIdMap.size() == 2) {
Dominik Laskowski075d3172018-05-24 15:50:06 -07001126 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001127 return true;
1128 }
1129
1130 return false;
1131}
1132
Peiyong Line9d809e2020-04-14 13:10:48 -07001133std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
1134 hal::HWDisplayId hwcDisplayId) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001135 std::optional<DisplayIdentificationInfo> info;
1136 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
1137 info = DisplayIdentificationInfo{.id = *displayId,
1138 .name = std::string(),
1139 .deviceProductInfo = std::nullopt};
Marin Shalamanovf8c63722020-10-06 13:11:21 +02001140 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);
Lucas Berthou8d0a0c42024-08-27 14:32:31 +00001146 info->preferredDetailedTimingDescriptor =
1147 std::move(newInfo->preferredDetailedTimingDescriptor);
Marin Shalamanovf8c63722020-10-06 13:11:21 +02001148 } else {
1149 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
1150 }
1151 }
Dominik Laskowski075d3172018-05-24 15:50:06 -07001152 } else {
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001153 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] {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001168 const bool isPrimary = !mPrimaryHwcDisplayId;
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001169 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);
Peiyong Lin65248e02020-04-18 21:15:07 -07001177 port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001178 }
1179
Marin Shalamanova524a092020-07-27 21:39:55 +02001180 return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001181 .name = isPrimary ? "Primary display"
1182 : "Secondary display",
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001183 .deviceProductInfo = std::nullopt};
1184 }();
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -04001185
1186 mComposer->onHotplugConnect(hwcDisplayId);
Dominik Laskowski075d3172018-05-24 15:50:06 -07001187 }
1188
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001189 if (!isConnected(info->id)) {
Lucas Berthou8d0a0c42024-08-27 14:32:31 +00001190 std::optional<ui::Size> size = std::nullopt;
1191 if (info->preferredDetailedTimingDescriptor) {
1192 size = info->preferredDetailedTimingDescriptor->physicalSizeInMm;
1193 }
1194 allocatePhysicalDisplay(hwcDisplayId, info->id, size);
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001195 }
1196 return info;
1197}
1198
1199std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
Peiyong Line9d809e2020-04-14 13:10:48 -07001200 hal::HWDisplayId hwcDisplayId) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001201 LOG_ALWAYS_FATAL_IF(hwcDisplayId == mPrimaryHwcDisplayId,
1202 "Primary display cannot be disconnected.");
1203
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001204 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
1205 if (!displayId) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001206 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001207 return {};
Dominik Laskowski075d3172018-05-24 15:50:06 -07001208 }
1209
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001210 if (!isConnected(*displayId)) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001211 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Already disconnected");
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001212 return {};
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001213 }
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001214
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);
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -04001218 mComposer->onHotplugDisconnect(hwcDisplayId);
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001219 return DisplayIdentificationInfo{.id = *displayId};
Steven Thomas6e8f7062017-11-22 14:15:29 -08001220}
1221
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001222void HWComposer::loadCapabilities() {
Peiyong Line9d809e2020-04-14 13:10:48 -07001223 static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001224 auto capabilities = mComposer->getCapabilities();
1225 for (auto capability : capabilities) {
Ady Abrahamde549d42022-01-26 19:19:17 -08001226 mCapabilities.emplace(capability);
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001227 }
1228}
1229
Sally Qibb866c12022-10-17 11:31:20 -07001230void HWComposer::loadOverlayProperties() {
1231 mComposer->getOverlaySupport(&mOverlayProperties);
1232}
1233
Kriti Dang674b9372022-11-18 10:58:44 +01001234void 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
ramindani32cf0602022-03-02 02:30:29 +00001242status_t HWComposer::setIdleTimerEnabled(PhysicalDisplayId displayId,
1243 std::chrono::milliseconds timeout) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +00001244 SFTRACE_CALL();
ramindani32cf0602022-03-02 02:30:29 +00001245 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
ramindani06e518e2022-03-14 18:47:53 +00001257bool HWComposer::hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) const {
ramindani32cf0602022-03-02 02:30:29 +00001258 RETURN_IF_INVALID_DISPLAY(displayId, false);
ramindani06e518e2022-03-14 18:47:53 +00001259 return mDisplayData.at(displayId).hwcDisplay->hasDisplayIdleTimerCapability();
1260}
1261
1262Hwc2::AidlTransform HWComposer::getPhysicalDisplayOrientation(PhysicalDisplayId displayId) const {
Vishnu Nairbe0ad902024-06-27 23:38:43 +00001263 SFTRACE_CALL();
ramindani06e518e2022-03-14 18:47:53 +00001264 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;
ramindani32cf0602022-03-02 02:30:29 +00001270}
1271
Lloyd Pique4603f3c2020-02-11 12:06:56 -08001272void 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) {
Ady Abraham3891cbe2021-03-29 11:29:31 -07001278 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 }
Lloyd Pique4603f3c2020-02-11 12:06:56 -08001282 return;
1283 }
1284
1285 for (const auto& [name, mandatory] : supportedMetadataKeyInfo) {
1286 mSupportedLayerGenericMetadata.emplace(name, mandatory);
1287 }
1288}
1289
Lloyd Pique441d5042018-10-18 16:49:51 -07001290} // namespace impl
Dominik Laskowskif9750f22018-06-06 12:24:53 -07001291} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001292
1293// TODO(b/129481165): remove the #pragma below and fix conversion issues
1294#pragma clang diagnostic pop // ignored "-Wconversion"