blob: 9943856297d0b06c34218e810d142e9ad88e704d [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,
339 .vrrConfig = config.vrrConfig};
ramindani0cd1d8d2023-06-13 13:43:23 -0700340
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000341 const DisplayConfiguration::Dpi estimatedDPI =
342 getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
ramindani0cd1d8d2023-06-13 13:43:23 -0700343 if (config.dpi) {
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000344 const DisplayConfiguration::Dpi dpi =
345 correctedDpiIfneeded(config.dpi.value(), estimatedDPI);
346 hwcMode.dpiX = dpi.x;
347 hwcMode.dpiY = dpi.y;
348 } else if (estimatedDPI.x != -1 && estimatedDPI.y != -1) {
349 hwcMode.dpiX = estimatedDPI.x;
350 hwcMode.dpiY = estimatedDPI.y;
ramindani0cd1d8d2023-06-13 13:43:23 -0700351 }
352
ramindani355fca82023-12-18 12:07:34 -0800353 if (!mEnableVrrTimeout) {
354 hwcMode.vrrConfig->notifyExpectedPresentConfig = {};
355 }
356
ramindani0cd1d8d2023-06-13 13:43:23 -0700357 modes.push_back(hwcMode);
358 }
359
360 return modes;
361}
362
363std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromLegacyDisplayConfigs(
364 uint64_t hwcDisplayId) const {
Marin Shalamanov045b7002021-01-07 16:56:24 +0100365 std::vector<hal::HWConfigId> configIds;
366 auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
367 RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
368
369 std::vector<HWCDisplayMode> modes;
370 modes.reserve(configIds.size());
371 for (auto configId : configIds) {
ramindani0cd1d8d2023-06-13 13:43:23 -0700372 auto hwcMode = HWCDisplayMode{
Marin Shalamanov045b7002021-01-07 16:56:24 +0100373 .hwcId = configId,
374 .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
375 .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
376 .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
Marin Shalamanov045b7002021-01-07 16:56:24 +0100377 .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
ramindani0cd1d8d2023-06-13 13:43:23 -0700378 };
Marin Shalamanov045b7002021-01-07 16:56:24 +0100379
ramindani0cd1d8d2023-06-13 13:43:23 -0700380 const int32_t dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X);
381 const int32_t dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y);
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000382 const DisplayConfiguration::Dpi hwcDpi =
Lucas Berthouae3611d2024-10-16 19:58:52 +0000383 DisplayConfiguration::Dpi{dpiX == -1 ? dpiX : dpiX / 1000.f,
Lucas Berthou8d0a0c42024-08-27 14:32:31 +0000384 dpiY == -1 ? dpiY : dpiY / 1000.f};
385 const DisplayConfiguration::Dpi estimatedDPI =
386 getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
387 const DisplayConfiguration::Dpi dpi = correctedDpiIfneeded(hwcDpi, estimatedDPI);
388 hwcMode.dpiX = dpi.x;
389 hwcMode.dpiY = dpi.y;
ramindani0cd1d8d2023-06-13 13:43:23 -0700390
391 modes.push_back(hwcMode);
392 }
Marin Shalamanov045b7002021-01-07 16:56:24 +0100393 return modes;
Mathias Agopianda27af92012-09-13 18:17:13 -0700394}
395
Dominik Laskowskid940a012024-01-28 13:25:44 -0500396ftl::Expected<hal::HWConfigId, status_t> HWComposer::getActiveMode(
397 PhysicalDisplayId displayId) const {
398 RETURN_IF_INVALID_DISPLAY(displayId, ftl::Unexpected(BAD_INDEX));
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100399 const auto hwcId = *fromPhysicalDisplayId(displayId);
Dominik Laskowskie2c5b0a2022-08-10 14:53:53 -0700400
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100401 hal::HWConfigId configId;
Dominik Laskowskie2c5b0a2022-08-10 14:53:53 -0700402 const auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
Dominik Laskowskid940a012024-01-28 13:25:44 -0500403 if (error == hal::Error::BAD_CONFIG) {
404 return ftl::Unexpected(NO_INIT);
405 }
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100406
Dominik Laskowskid940a012024-01-28 13:25:44 -0500407 RETURN_IF_HWC_ERROR_FOR("getActiveConfig", error, displayId, ftl::Unexpected(UNKNOWN_ERROR));
Marin Shalamanov045b7002021-01-07 16:56:24 +0100408 return configId;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700409}
410
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800411// Composer 2.4
412
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100413ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
414 RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal);
Dominik Laskowski55c85402020-01-21 16:25:47 -0800415 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
416
Dominik Laskowski969cdcb2024-02-08 16:35:29 -0500417 if (const auto connectionType = hwcDisplay->getConnectionType()) {
418 return connectionType.value();
419 } else {
420 LOG_HWC_ERROR(__func__, connectionType.error(), displayId);
421 return hwcDisplay->getId() == mPrimaryHwcDisplayId ? ui::DisplayConnectionType::Internal
422 : ui::DisplayConnectionType::External;
423 }
Dominik Laskowski55c85402020-01-21 16:25:47 -0800424}
425
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200426bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const {
Dominik Laskowski55c85402020-01-21 16:25:47 -0800427 RETURN_IF_INVALID_DISPLAY(displayId, false);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800428 return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
429}
430
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500431ftl::Expected<nsecs_t, status_t> HWComposer::getDisplayVsyncPeriod(
432 PhysicalDisplayId displayId) const {
433 RETURN_IF_INVALID_DISPLAY(displayId, ftl::Unexpected(BAD_INDEX));
Dominik Laskowski55c85402020-01-21 16:25:47 -0800434
Marin Shalamanov045b7002021-01-07 16:56:24 +0100435 if (!isVsyncPeriodSwitchSupported(displayId)) {
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500436 return ftl::Unexpected(INVALID_OPERATION);
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700437 }
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500438
Marin Shalamanov045b7002021-01-07 16:56:24 +0100439 const auto hwcId = *fromPhysicalDisplayId(displayId);
440 Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500441 const auto error =
Marin Shalamanov045b7002021-01-07 16:56:24 +0100442 static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
Dominik Laskowskia109bb22024-01-28 13:33:51 -0500443 RETURN_IF_HWC_ERROR(error, displayId, ftl::Unexpected(UNKNOWN_ERROR));
444 return static_cast<nsecs_t>(vsyncPeriodNanos);
Lloyd Pique3c085a02018-05-09 19:38:32 -0700445}
446
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200447std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700448 RETURN_IF_INVALID_DISPLAY(displayId, {});
449
Peiyong Linfd997e02018-03-28 15:29:00 -0700450 std::vector<ui::ColorMode> modes;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700451 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700452 RETURN_IF_HWC_ERROR(error, displayId, {});
Courtney Goeltzenleuchterfad9d8c2016-06-23 11:49:50 -0600453 return modes;
454}
455
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200456status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700457 ui::RenderIntent renderIntent) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700458 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Michael Wright28f24d02016-07-12 13:30:53 -0700459
460 auto& displayData = mDisplayData[displayId];
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700461 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700462 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
463 decodeRenderIntent(renderIntent) + ")")
464 .c_str(),
465 error, displayId, UNKNOWN_ERROR);
Michael Wright28f24d02016-07-12 13:30:53 -0700466
467 return NO_ERROR;
468}
469
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200470void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700471 RETURN_IF_INVALID_DISPLAY(displayId);
472 auto& displayData = mDisplayData[displayId];
473
Dan Stoza9e56aa02015-11-02 13:00:03 -0800474 // NOTE: we use our own internal lock here because we have to call
475 // into the HWC with the lock held, and we want to make sure
476 // that even if HWC blocks (which it shouldn't), it won't
477 // affect other threads.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800478 std::lock_guard lock(displayData.vsyncEnabledLock);
479 if (enabled == displayData.vsyncEnabled) {
480 return;
Colin Cross10fbdb62012-07-12 17:56:34 -0700481 }
Dominik Laskowski1af47932018-11-12 10:20:46 -0800482
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000483 SFTRACE_CALL();
Dominik Laskowski1af47932018-11-12 10:20:46 -0800484 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
485 RETURN_IF_HWC_ERROR(error, displayId);
486
487 displayData.vsyncEnabled = enabled;
488
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000489 SFTRACE_INT(ftl::Concat("HW_VSYNC_ON_", displayId.value).c_str(),
490 enabled == hal::Vsync::ENABLE ? 1 : 0);
Colin Cross10fbdb62012-07-12 17:56:34 -0700491}
492
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200493status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700494 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
Alec Mourif97df4d2023-09-06 02:10:05 +0000495 ui::Dataspace dataspace, float hdrSdrRatio) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700496 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Jesse Hall851cfe82013-03-20 13:44:00 -0700497
Dominik Laskowski34157762018-10-31 13:07:19 -0700498 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
Dan Stoza9e56aa02015-11-02 13:00:03 -0800499 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Alec Mourif97df4d2023-09-06 02:10:05 +0000500 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace, hdrSdrRatio);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700501 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
Jesse Hall851cfe82013-03-20 13:44:00 -0700502 return NO_ERROR;
503}
504
Lloyd Pique66d68602019-02-13 14:23:31 -0800505status_t HWComposer::getDeviceCompositionChanges(
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200506 HalDisplayId displayId, bool frameUsesClientComposition,
Ady Abrahamf1db8032023-03-24 17:52:34 -0700507 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime,
ramindani4aac32c2023-10-30 14:13:30 -0700508 nsecs_t expectedPresentTime, Fps frameInterval,
Lloyd Pique66d68602019-02-13 14:23:31 -0800509 std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000510 SFTRACE_CALL();
Dan Stoza9e56aa02015-11-02 13:00:03 -0800511
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700512 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800513
514 auto& displayData = mDisplayData[displayId];
515 auto& hwcDisplay = displayData.hwcDisplay;
516 if (!hwcDisplay->isConnected()) {
517 return NO_ERROR;
518 }
519
520 uint32_t numTypes = 0;
521 uint32_t numRequests = 0;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700522
Peiyong Line9d809e2020-04-14 13:10:48 -0700523 hal::Error error = hal::Error::NONE;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700524
Ady Abrahamec7aa8a2021-06-28 12:37:09 -0700525 // First try to skip validate altogether. We can do that when
526 // 1. The previous frame has not been presented yet or already passed the
527 // earliest time to present. Otherwise, we may present a frame too early.
528 // 2. There is no client composition. Otherwise, we first need to render the
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700529 // client target buffer.
Ady Abraham43065bd2021-12-10 17:22:15 -0800530 const bool canSkipValidate = [&] {
531 // We must call validate if we have client composition
532 if (frameUsesClientComposition) {
533 return false;
534 }
535
536 // If composer supports getting the expected present time, we can skip
537 // as composer will make sure to prevent early presentation
Ady Abrahamf1db8032023-03-24 17:52:34 -0700538 if (!earliestPresentTime) {
Ady Abraham43065bd2021-12-10 17:22:15 -0800539 return true;
540 }
541
542 // composer doesn't support getting the expected present time. We can only
543 // skip validate if we know that we are not going to present early.
Ady Abrahamf1db8032023-03-24 17:52:34 -0700544 return std::chrono::steady_clock::now() >= *earliestPresentTime;
Ady Abraham43065bd2021-12-10 17:22:15 -0800545 }();
546
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700547 displayData.validateWasSkipped = false;
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000548 SFTRACE_FORMAT("NextFrameInterval %d_Hz", frameInterval.getIntValue());
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700549 if (canSkipValidate) {
Leon Scroggins IIIabc2c452023-11-08 17:04:51 -0500550 sp<Fence> outPresentFence = Fence::NO_FENCE;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700551 uint32_t state = UINT32_MAX;
ramindani4aac32c2023-10-30 14:13:30 -0700552 error = hwcDisplay->presentOrValidate(expectedPresentTime, frameInterval.getPeriodNsecs(),
553 &numTypes, &numRequests, &outPresentFence, &state);
Peiyong Line9d809e2020-04-14 13:10:48 -0700554 if (!hasChangesError(error)) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700555 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700556 }
557 if (state == 1) { //Present Succeeded.
Steven Thomas94e35b92017-07-26 18:48:28 -0700558 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700559 error = hwcDisplay->getReleaseFences(&releaseFences);
560 displayData.releaseFences = std::move(releaseFences);
561 displayData.lastPresentFence = outPresentFence;
562 displayData.validateWasSkipped = true;
563 displayData.presentError = error;
564 return NO_ERROR;
565 }
566 // Present failed but Validate ran.
567 } else {
ramindani09acbb82023-11-03 09:02:38 -0700568 error = hwcDisplay->validate(expectedPresentTime, frameInterval.getPeriodNsecs(), &numTypes,
569 &numRequests);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700570 }
571 ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
Peiyong Line9d809e2020-04-14 13:10:48 -0700572 if (!hasChangesError(error)) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700573 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800574 }
575
Lloyd Pique66d68602019-02-13 14:23:31 -0800576 android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800577 changedTypes.reserve(numTypes);
578 error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700579 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800580
Peiyong Line9d809e2020-04-14 13:10:48 -0700581 auto displayRequests = static_cast<hal::DisplayRequest>(0);
Lloyd Pique66d68602019-02-13 14:23:31 -0800582 android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800583 layerRequests.reserve(numRequests);
Lloyd Pique66d68602019-02-13 14:23:31 -0800584 error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700585 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800586
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700587 DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
Alec Mouri85065692022-03-18 00:58:26 +0000588 error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
Sally Qi11dcd582024-08-16 18:11:27 -0700589 RETURN_IF_HWC_ERROR_FOR("getClientTargetProperty", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800590
Sally Qi95f669a2024-08-27 11:31:42 -0700591 DeviceRequestedChanges::LayerLuts layerLuts;
592 error = hwcDisplay->getRequestedLuts(&layerLuts, mLutFileDescriptorMapper);
593 RETURN_IF_HWC_ERROR_FOR("getRequestedLuts", error, displayId, BAD_INDEX);
594
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700595 outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
596 std::move(layerRequests),
Sally Qi95f669a2024-08-27 11:31:42 -0700597 std::move(clientTargetProperty),
598 std::move(layerLuts)});
Dan Stoza9e56aa02015-11-02 13:00:03 -0800599 error = hwcDisplay->acceptChanges();
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700600 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800601
602 return NO_ERROR;
603}
604
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200605sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700606 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700607 return mDisplayData.at(displayId).lastPresentFence;
Jesse Hall851cfe82013-03-20 13:44:00 -0700608}
609
Dominik Laskowskidc2bb802022-09-28 16:02:59 -0400610nsecs_t HWComposer::getPresentTimestamp(PhysicalDisplayId displayId) const {
611 RETURN_IF_INVALID_DISPLAY(displayId, 0);
612 return mDisplayData.at(displayId).lastPresentTimestamp;
613}
614
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200615sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700616 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Tim Murray2d3f8b82019-12-04 16:24:17 -0800617 const auto& displayFences = mDisplayData.at(displayId).releaseFences;
618 auto fence = displayFences.find(layer);
619 if (fence == displayFences.end()) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800620 ALOGV("getLayerReleaseFence: Release fence not found");
621 return Fence::NO_FENCE;
Riley Andrews03414a12014-07-01 14:22:59 -0700622 }
Tim Murray2d3f8b82019-12-04 16:24:17 -0800623 return fence->second;
Riley Andrews03414a12014-07-01 14:22:59 -0700624}
625
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700626status_t HWComposer::presentAndGetReleaseFences(
Ady Abrahamf1db8032023-03-24 17:52:34 -0700627 HalDisplayId displayId,
628 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000629 SFTRACE_CALL();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700630
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700631 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Pablo Ceballosd814cf22015-09-11 14:37:39 -0700632
Dan Stoza9e56aa02015-11-02 13:00:03 -0800633 auto& displayData = mDisplayData[displayId];
634 auto& hwcDisplay = displayData.hwcDisplay;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700635
636 if (displayData.validateWasSkipped) {
Chia-I Wuae5a6b82017-10-10 09:09:22 -0700637 // explicitly flush all pending commands
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -0400638 auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800639 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700640 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700641 return NO_ERROR;
642 }
643
Ady Abrahamf1db8032023-03-24 17:52:34 -0700644 if (earliestPresentTime) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000645 SFTRACE_NAME("wait for earliest present time");
Ady Abrahamf1db8032023-03-24 17:52:34 -0700646 std::this_thread::sleep_until(*earliestPresentTime);
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700647 }
648
Fabien Sanglard11d0fc32016-12-01 15:43:01 -0800649 auto error = hwcDisplay->present(&displayData.lastPresentFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700650 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700651
Steven Thomas94e35b92017-07-26 18:48:28 -0700652 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800653 error = hwcDisplay->getReleaseFences(&releaseFences);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700654 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800655
656 displayData.releaseFences = std::move(releaseFences);
657
658 return NO_ERROR;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700659}
660
Leon Scroggins IIIa3ba7fa2024-05-22 16:34:52 -0400661status_t HWComposer::executeCommands(HalDisplayId displayId) {
662 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
663 auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
664 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
665 return NO_ERROR;
666}
667
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200668status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700669 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
670
Peiyong Line9d809e2020-04-14 13:10:48 -0700671 if (mode == hal::PowerMode::OFF) {
672 setVsyncEnabled(displayId, hal::Vsync::DISABLE);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800673 }
674
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700675 const auto& displayData = mDisplayData[displayId];
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700676 auto& hwcDisplay = displayData.hwcDisplay;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800677 switch (mode) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700678 case hal::PowerMode::OFF:
679 case hal::PowerMode::ON:
Dan Stoza9e56aa02015-11-02 13:00:03 -0800680 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
681 {
682 auto error = hwcDisplay->setPowerMode(mode);
Peiyong Line9d809e2020-04-14 13:10:48 -0700683 if (error != hal::Error::NONE) {
684 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
685 displayId);
Peiyong Lin306e4992018-05-07 16:18:22 -0700686 }
Mathias Agopianda27af92012-09-13 18:17:13 -0700687 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800688 break;
Peiyong Line9d809e2020-04-14 13:10:48 -0700689 case hal::PowerMode::DOZE:
690 case hal::PowerMode::DOZE_SUSPEND:
Dan Stoza9e56aa02015-11-02 13:00:03 -0800691 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
692 {
693 bool supportsDoze = false;
Leon Scroggins III689c80f2023-06-05 17:49:32 -0400694 const auto queryDozeError = hwcDisplay->supportsDoze(&supportsDoze);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700695
Leon Scroggins III689c80f2023-06-05 17:49:32 -0400696 // queryDozeError might be NO_RESOURCES, in the case of a display that has never
697 // been turned on. In that case, attempt to set to DOZE anyway.
698 if (!supportsDoze && queryDozeError == hal::Error::NONE) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700699 mode = hal::PowerMode::ON;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800700 }
701
Leon Scroggins III689c80f2023-06-05 17:49:32 -0400702 auto error = hwcDisplay->setPowerMode(mode);
Peiyong Line9d809e2020-04-14 13:10:48 -0700703 if (error != hal::Error::NONE) {
704 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
705 displayId);
Leon Scroggins III689c80f2023-06-05 17:49:32 -0400706 // If the display had never been turned on, so its doze
707 // support was unknown, it may truly not support doze. Try
708 // switching it to ON instead.
709 if (queryDozeError == hal::Error::NO_RESOURCES) {
710 ALOGD("%s: failed to set %s to %s. Trying again with ON", __func__,
711 to_string(displayId).c_str(), to_string(mode).c_str());
712 error = hwcDisplay->setPowerMode(hal::PowerMode::ON);
713 if (error != hal::Error::NONE) {
714 LOG_HWC_ERROR("setPowerMode(ON)", error, displayId);
715 }
716 }
Peiyong Lin306e4992018-05-07 16:18:22 -0700717 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800718 }
719 break;
720 default:
721 ALOGV("setPowerMode: Not calling HWC");
722 break;
Mathias Agopianda27af92012-09-13 18:17:13 -0700723 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800724
725 return NO_ERROR;
726}
727
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100728status_t HWComposer::setActiveModeWithConstraints(
Marin Shalamanov12c9e5a2021-01-07 00:25:35 +0100729 PhysicalDisplayId displayId, hal::HWConfigId hwcModeId,
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200730 const hal::VsyncPeriodChangeConstraints& constraints,
Peiyong Line9d809e2020-04-14 13:10:48 -0700731 hal::VsyncPeriodChangeTimeline* outTimeline) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700732 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800733
Marin Shalamanov12c9e5a2021-01-07 00:25:35 +0100734 auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
735 constraints,
736 outTimeline);
Manasi Navarefc2a4a72024-11-12 23:59:21 +0000737 if (error == hal::Error::CONFIG_FAILED) {
738 RETURN_IF_HWC_ERROR_FOR("setActiveConfigWithConstraints", error, displayId,
739 FAILED_TRANSACTION);
740 }
741 RETURN_IF_HWC_ERROR_FOR("setActiveConfigWithConstraints", error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800742 return NO_ERROR;
743}
744
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200745status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700746 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700747
748 auto& displayData = mDisplayData[displayId];
Ady Abrahamdc011a92021-12-21 14:06:44 -0800749 auto error = displayData.hwcDisplay->setColorTransform(transform);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700750 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700751 return NO_ERROR;
752}
753
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200754void HWComposer::disconnectDisplay(HalDisplayId displayId) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700755 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800756 auto& displayData = mDisplayData[displayId];
Dominik Laskowski7e045462018-05-30 13:02:02 -0700757 const auto hwcDisplayId = displayData.hwcDisplay->getId();
Dominik Laskowski075d3172018-05-24 15:50:06 -0700758
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800759 mPhysicalDisplayIdMap.erase(hwcDisplayId);
760 mDisplayData.erase(displayId);
Marin Shalamanov8b196592021-08-09 16:24:42 +0200761
762 // Reset the primary display ID if we're disconnecting it.
763 // This way isHeadless() will return false, which is necessary
764 // because getPrimaryDisplayId() will crash.
765 if (mPrimaryHwcDisplayId == hwcDisplayId) {
766 mPrimaryHwcDisplayId.reset();
767 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800768}
769
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200770status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700771 const sp<GraphicBuffer>& buffer) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700772 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700773 const auto& displayData = mDisplayData[displayId];
Dan Stoza9e56aa02015-11-02 13:00:03 -0800774
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700775 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700776 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800777 return NO_ERROR;
778}
779
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200780void HWComposer::clearReleaseFences(HalDisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700781 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800782 mDisplayData[displayId].releaseFences.clear();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700783}
784
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200785status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700786 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stozac4f471e2016-03-24 09:31:08 -0700787
788 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Peiyong Lin62665892018-04-16 11:07:44 -0700789 auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700790 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Peiyong Lin62665892018-04-16 11:07:44 -0700791 return NO_ERROR;
Dan Stozac4f471e2016-03-24 09:31:08 -0700792}
793
Sally Qibb866c12022-10-17 11:31:20 -0700794const aidl::android::hardware::graphics::composer3::OverlayProperties&
795HWComposer::getOverlaySupport() const {
796 return mOverlayProperties;
Sally Qi0cbd08b2022-08-17 12:12:28 -0700797}
798
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200799int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700800 RETURN_IF_INVALID_DISPLAY(displayId, 0);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700801 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
Peiyong Lin0ac5f4e2018-04-19 22:06:34 -0700802}
803
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200804std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700805 ui::ColorMode colorMode) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700806 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700807
808 std::vector<ui::RenderIntent> renderIntents;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700809 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700810 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700811 return renderIntents;
812}
813
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200814mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700815 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700816
817 mat4 matrix;
818 auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
819 &matrix);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700820 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700821 return matrix;
822}
823
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200824status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId,
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700825 ui::PixelFormat* outFormat,
826 ui::Dataspace* outDataspace,
827 uint8_t* outComponentMask) {
828 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
829 const auto error =
830 mDisplayData[displayId]
831 .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
832 outComponentMask);
Peiyong Line9d809e2020-04-14 13:10:48 -0700833 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700834 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
835 return NO_ERROR;
836}
837
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200838status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled,
Kevin DuBois74e53772018-11-19 10:52:38 -0800839 uint8_t componentMask, uint64_t maxFrames) {
840 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
841 const auto error =
842 mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
843 componentMask,
844 maxFrames);
845
Peiyong Line9d809e2020-04-14 13:10:48 -0700846 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
847 if (error == hal::Error::BAD_PARAMETER) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
Kevin DuBois74e53772018-11-19 10:52:38 -0800848 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
849 return NO_ERROR;
850}
851
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200852status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames,
Kevin DuBois1d4249a2018-08-29 10:45:14 -0700853 uint64_t timestamp, DisplayedFrameStats* outStats) {
854 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
855 const auto error =
856 mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
857 outStats);
858 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
859 return NO_ERROR;
860}
861
Dominik Laskowskib17c6212022-05-09 09:36:19 -0700862ftl::Future<status_t> HWComposer::setDisplayBrightness(
Alec Mouri4d8a05d2022-03-23 18:14:26 +0000863 PhysicalDisplayId displayId, float brightness, float brightnessNits,
Alec Mouricdf16792021-12-10 13:16:06 -0800864 const Hwc2::Composer::DisplayBrightnessOptions& options) {
Dominik Laskowski4e2b71f2020-11-10 15:05:32 -0800865 RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX));
Dominik Laskowski5690bde2020-04-23 19:04:22 -0700866 auto& display = mDisplayData[displayId].hwcDisplay;
867
Dominik Laskowskib17c6212022-05-09 09:36:19 -0700868 return display->setDisplayBrightness(brightness, brightnessNits, options)
Dominik Laskowski5690bde2020-04-23 19:04:22 -0700869 .then([displayId](hal::Error error) -> status_t {
870 if (error == hal::Error::UNSUPPORTED) {
871 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
872 }
873 if (error == hal::Error::BAD_PARAMETER) {
874 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
875 }
876 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
877 return NO_ERROR;
878 });
Dan Gittik57e63c52019-01-18 16:37:54 +0000879}
880
Matt Buckley50c44062022-01-17 20:48:10 +0000881bool HWComposer::getValidateSkipped(HalDisplayId displayId) const {
882 if (mDisplayData.count(displayId) == 0) {
883 return false;
884 }
885 return mDisplayData.at(displayId).validateWasSkipped;
886}
887
Kriti Dang7defaf32021-11-15 11:55:43 +0100888status_t HWComposer::setBootDisplayMode(PhysicalDisplayId displayId,
889 hal::HWConfigId displayModeId) {
890 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
891 const auto error = mDisplayData[displayId].hwcDisplay->setBootDisplayConfig(displayModeId);
892 if (error == hal::Error::UNSUPPORTED) {
893 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
894 }
895 if (error == hal::Error::BAD_PARAMETER) {
896 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
897 }
898 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
899 return NO_ERROR;
900}
901
902status_t HWComposer::clearBootDisplayMode(PhysicalDisplayId displayId) {
903 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
904 const auto error = mDisplayData[displayId].hwcDisplay->clearBootDisplayConfig();
905 if (error == hal::Error::UNSUPPORTED) {
906 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
907 }
908 if (error == hal::Error::BAD_PARAMETER) {
909 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
910 }
911 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
912 return NO_ERROR;
913}
914
Kriti Dang16ca2972022-02-01 20:07:03 +0100915std::optional<hal::HWConfigId> HWComposer::getPreferredBootDisplayMode(
916 PhysicalDisplayId displayId) {
917 RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
918 hal::HWConfigId displayModeId;
Kriti Dang7defaf32021-11-15 11:55:43 +0100919 const auto error =
920 mDisplayData[displayId].hwcDisplay->getPreferredBootDisplayConfig(&displayModeId);
Kriti Dang16ca2972022-02-01 20:07:03 +0100921 if (error != hal::Error::NONE) {
922 LOG_DISPLAY_ERROR(displayId, to_string(error).c_str());
923 return std::nullopt;
Kriti Dang7defaf32021-11-15 11:55:43 +0100924 }
Kriti Dang7defaf32021-11-15 11:55:43 +0100925 return displayModeId;
926}
927
Kriti Dang674b9372022-11-18 10:58:44 +0100928std::vector<HdrConversionCapability> HWComposer::getHdrConversionCapabilities() const {
929 return mHdrConversionCapabilities;
930}
931
Kriti Dangd432bb52023-02-09 18:21:04 +0100932status_t HWComposer::setHdrConversionStrategy(
933 HdrConversionStrategy hdrConversionStrategy,
934 aidl::android::hardware::graphics::common::Hdr* outPreferredHdrOutputType) {
935 const auto error =
936 mComposer->setHdrConversionStrategy(hdrConversionStrategy, outPreferredHdrOutputType);
Kriti Dang674b9372022-11-18 10:58:44 +0100937 if (error != hal::Error::NONE) {
938 ALOGE("Error in setting HDR conversion strategy %s", to_string(error).c_str());
Kriti Dangd432bb52023-02-09 18:21:04 +0100939 return INVALID_OPERATION;
Kriti Dang674b9372022-11-18 10:58:44 +0100940 }
941 return NO_ERROR;
942}
943
ramindanib2158ee2023-02-13 20:29:59 -0800944status_t HWComposer::setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId displayId,
945 bool enabled) {
946 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
947 const auto error =
948 mComposer->setRefreshRateChangedCallbackDebugEnabled(mDisplayData[displayId]
949 .hwcDisplay->getId(),
950 enabled);
951 if (error != hal::Error::NONE) {
952 ALOGE("Error in setting refresh refresh rate change callback debug enabled %s",
953 to_string(error).c_str());
954 return INVALID_OPERATION;
955 }
956 return NO_ERROR;
957}
958
ramindanic67d22c2023-11-28 14:58:47 -0800959status_t HWComposer::notifyExpectedPresent(PhysicalDisplayId displayId,
960 TimePoint expectedPresentTime, Fps frameInterval) {
ramindani3acaaf52023-09-25 10:31:27 -0700961 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000962 SFTRACE_FORMAT("%s ExpectedPresentTime in %.2fms frameInterval %.2fms", __func__,
963 ticks<std::milli, float>(expectedPresentTime - TimePoint::now()),
964 ticks<std::milli, float>(Duration::fromNs(frameInterval.getPeriodNsecs())));
ramindanic67d22c2023-11-28 14:58:47 -0800965 const auto error = mComposer->notifyExpectedPresent(mDisplayData[displayId].hwcDisplay->getId(),
ramindanif8c0f102023-10-09 12:42:57 -0700966 expectedPresentTime.ns(),
967 frameInterval.getPeriodNsecs());
ramindani3acaaf52023-09-25 10:31:27 -0700968 if (error != hal::Error::NONE) {
969 ALOGE("Error in notifyExpectedPresent call %s", to_string(error).c_str());
970 return INVALID_OPERATION;
971 }
972 return NO_ERROR;
973}
974
Leon Scroggins IIIe7c51c62022-02-01 15:53:54 -0500975status_t HWComposer::getDisplayDecorationSupport(
976 PhysicalDisplayId displayId,
977 std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
978 support) {
979 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
980 const auto error = mDisplayData[displayId].hwcDisplay->getDisplayDecorationSupport(support);
981 if (error == hal::Error::UNSUPPORTED) {
982 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
983 }
984 if (error == hal::Error::BAD_PARAMETER) {
985 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
986 }
987 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
988 return NO_ERROR;
989}
990
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200991status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100992 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
993 const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
Peiyong Line9d809e2020-04-14 13:10:48 -0700994 if (error == hal::Error::UNSUPPORTED) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100995 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
996 }
Peiyong Line9d809e2020-04-14 13:10:48 -0700997 if (error == hal::Error::BAD_PARAMETER) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100998 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
999 }
1000 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1001 return NO_ERROR;
1002}
1003
1004status_t HWComposer::getSupportedContentTypes(
Dominik Laskowski6c7b36e2022-03-03 08:27:58 -08001005 PhysicalDisplayId displayId,
1006 std::vector<hal::ContentType>* outSupportedContentTypes) const {
Galia Peycheva5492cb52019-10-30 14:13:16 +01001007 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dominik Laskowski6c7b36e2022-03-03 08:27:58 -08001008 const auto error = mDisplayData.at(displayId).hwcDisplay->getSupportedContentTypes(
1009 outSupportedContentTypes);
Galia Peycheva5492cb52019-10-30 14:13:16 +01001010
1011 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1012
1013 return NO_ERROR;
1014}
1015
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +02001016status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) {
Galia Peycheva5492cb52019-10-30 14:13:16 +01001017 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1018 const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
Peiyong Line9d809e2020-04-14 13:10:48 -07001019 if (error == hal::Error::UNSUPPORTED) {
Galia Peycheva5492cb52019-10-30 14:13:16 +01001020 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1021 }
Peiyong Line9d809e2020-04-14 13:10:48 -07001022 if (error == hal::Error::BAD_PARAMETER) {
Galia Peycheva5492cb52019-10-30 14:13:16 +01001023 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1024 }
1025 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1026
1027 return NO_ERROR;
1028}
1029
Brian Lindahl7a4cb7e2024-10-30 10:42:21 -06001030int32_t HWComposer::getMaxLayerPictureProfiles(PhysicalDisplayId displayId) {
1031 int32_t maxProfiles = 0;
1032 RETURN_IF_INVALID_DISPLAY(displayId, 0);
1033 const auto error = mDisplayData[displayId].hwcDisplay->getMaxLayerPictureProfiles(&maxProfiles);
1034 RETURN_IF_HWC_ERROR(error, displayId, 0);
1035 return maxProfiles;
1036}
1037
1038status_t HWComposer::setDisplayPictureProfileHandle(PhysicalDisplayId displayId,
1039 const PictureProfileHandle& handle) {
1040 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1041 const auto error = mDisplayData[displayId].hwcDisplay->setPictureProfileHandle(handle);
1042 if (error != hal::Error::UNSUPPORTED) {
1043 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1044 }
1045 return NO_ERROR;
1046}
1047
Lloyd Pique4603f3c2020-02-11 12:06:56 -08001048const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
1049 return mSupportedLayerGenericMetadata;
1050}
1051
Sally Qi95f669a2024-08-27 11:31:42 -07001052ftl::SmallMap<HWC2::Layer*, ndk::ScopedFileDescriptor, 20>&
1053HWComposer::getLutFileDescriptorMapper() {
1054 return mLutFileDescriptorMapper;
1055}
1056
Sally Qi254ef492024-04-08 15:01:28 -07001057void HWComposer::dumpOverlayProperties(std::string& result) const {
1058 // dump overlay properties
1059 result.append("OverlayProperties:\n");
1060 base::StringAppendF(&result, "supportMixedColorSpaces: %d\n",
1061 mOverlayProperties.supportMixedColorSpaces);
1062 base::StringAppendF(&result, "SupportedBufferCombinations(%zu entries)\n",
1063 mOverlayProperties.combinations.size());
1064 for (const auto& combination : mOverlayProperties.combinations) {
1065 result.append(" pixelFormats=\n");
1066 for (const auto& pixelFormat : combination.pixelFormats) {
1067 base::StringAppendF(&result, " %s (%d)\n",
1068 decodePixelFormat(static_cast<PixelFormat>(pixelFormat)).c_str(),
1069 static_cast<uint32_t>(pixelFormat));
1070 }
1071 result.append(" standards=\n");
1072 for (const auto& standard : combination.standards) {
1073 base::StringAppendF(&result, " %s (%d)\n",
Sally Qi5dfdf142024-04-15 16:50:24 +00001074 decodeStandardOnly(static_cast<uint32_t>(standard)).c_str(),
Sally Qi254ef492024-04-08 15:01:28 -07001075 static_cast<uint32_t>(standard));
1076 }
1077 result.append(" transfers=\n");
1078 for (const auto& transfer : combination.transfers) {
1079 base::StringAppendF(&result, " %s (%d)\n",
1080 decodeTransferOnly(static_cast<uint32_t>(transfer)).c_str(),
1081 static_cast<uint32_t>(transfer));
1082 }
1083 result.append(" ranges=\n");
1084 for (const auto& range : combination.ranges) {
1085 base::StringAppendF(&result, " %s (%d)\n",
1086 decodeRangeOnly(static_cast<uint32_t>(range)).c_str(),
1087 static_cast<uint32_t>(range));
1088 }
1089 result.append("\n");
1090 }
1091}
1092
Yiwei Zhang5434a782018-12-05 18:06:32 -08001093void HWComposer::dump(std::string& result) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001094 result.append(mComposer->dumpDebugInfo());
Sally Qi254ef492024-04-08 15:01:28 -07001095 dumpOverlayProperties(result);
Mathias Agopian83727852010-09-23 18:13:21 -07001096}
1097
Marin Shalamanova524a092020-07-27 21:39:55 +02001098std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
1099 hal::HWDisplayId hwcDisplayId) const {
Dominik Laskowski075d3172018-05-24 15:50:06 -07001100 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
1101 it != mPhysicalDisplayIdMap.end()) {
1102 return it->second;
1103 }
1104 return {};
1105}
1106
Marin Shalamanova524a092020-07-27 21:39:55 +02001107std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
1108 PhysicalDisplayId displayId) const {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001109 if (const auto it = mDisplayData.find(displayId); it != mDisplayData.end()) {
Dominik Laskowski075d3172018-05-24 15:50:06 -07001110 return it->second.hwcDisplay->getId();
1111 }
1112 return {};
1113}
1114
Peiyong Line9d809e2020-04-14 13:10:48 -07001115bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001116 bool hasDisplayIdentificationData) const {
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001117 if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
Dominik Laskowski075d3172018-05-24 15:50:06 -07001118 ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
1119 hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001120 return true;
Dominik Laskowski075d3172018-05-24 15:50:06 -07001121 }
1122
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001123 // Legacy mode only supports IDs LEGACY_DISPLAY_TYPE_PRIMARY and LEGACY_DISPLAY_TYPE_EXTERNAL.
1124 if (!mHasMultiDisplaySupport && mPhysicalDisplayIdMap.size() == 2) {
Dominik Laskowski075d3172018-05-24 15:50:06 -07001125 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001126 return true;
1127 }
1128
1129 return false;
1130}
1131
Peiyong Line9d809e2020-04-14 13:10:48 -07001132std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
1133 hal::HWDisplayId hwcDisplayId) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001134 std::optional<DisplayIdentificationInfo> info;
1135 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
1136 info = DisplayIdentificationInfo{.id = *displayId,
1137 .name = std::string(),
1138 .deviceProductInfo = std::nullopt};
Marin Shalamanovf8c63722020-10-06 13:11:21 +02001139 if (mUpdateDeviceProductInfoOnHotplugReconnect) {
1140 uint8_t port;
1141 DisplayIdentificationData data;
1142 getDisplayIdentificationData(hwcDisplayId, &port, &data);
1143 if (auto newInfo = parseDisplayIdentificationData(port, data)) {
1144 info->deviceProductInfo = std::move(newInfo->deviceProductInfo);
Lucas Berthou8d0a0c42024-08-27 14:32:31 +00001145 info->preferredDetailedTimingDescriptor =
1146 std::move(newInfo->preferredDetailedTimingDescriptor);
Marin Shalamanovf8c63722020-10-06 13:11:21 +02001147 } else {
1148 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
1149 }
1150 }
Dominik Laskowski075d3172018-05-24 15:50:06 -07001151 } else {
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001152 uint8_t port;
1153 DisplayIdentificationData data;
1154 const bool hasDisplayIdentificationData =
1155 getDisplayIdentificationData(hwcDisplayId, &port, &data);
1156 if (mPhysicalDisplayIdMap.empty()) {
1157 mHasMultiDisplaySupport = hasDisplayIdentificationData;
1158 ALOGI("Switching to %s multi-display mode",
1159 mHasMultiDisplaySupport ? "generalized" : "legacy");
1160 }
1161
1162 if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
1163 return {};
1164 }
1165
1166 info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001167 const bool isPrimary = !mPrimaryHwcDisplayId;
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001168 if (mHasMultiDisplaySupport) {
1169 if (const auto info = parseDisplayIdentificationData(port, data)) {
1170 return *info;
1171 }
1172 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
1173 } else {
1174 ALOGW_IF(hasDisplayIdentificationData,
1175 "Ignoring identification data for display %" PRIu64, hwcDisplayId);
Peiyong Lin65248e02020-04-18 21:15:07 -07001176 port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001177 }
1178
Marin Shalamanova524a092020-07-27 21:39:55 +02001179 return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001180 .name = isPrimary ? "Primary display"
1181 : "Secondary display",
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001182 .deviceProductInfo = std::nullopt};
1183 }();
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -04001184
1185 mComposer->onHotplugConnect(hwcDisplayId);
Dominik Laskowski075d3172018-05-24 15:50:06 -07001186 }
1187
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001188 if (!isConnected(info->id)) {
Lucas Berthou8d0a0c42024-08-27 14:32:31 +00001189 std::optional<ui::Size> size = std::nullopt;
1190 if (info->preferredDetailedTimingDescriptor) {
1191 size = info->preferredDetailedTimingDescriptor->physicalSizeInMm;
1192 }
1193 allocatePhysicalDisplay(hwcDisplayId, info->id, size);
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001194 }
1195 return info;
1196}
1197
1198std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
Peiyong Line9d809e2020-04-14 13:10:48 -07001199 hal::HWDisplayId hwcDisplayId) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001200 LOG_ALWAYS_FATAL_IF(hwcDisplayId == mPrimaryHwcDisplayId,
1201 "Primary display cannot be disconnected.");
1202
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001203 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
1204 if (!displayId) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001205 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001206 return {};
Dominik Laskowski075d3172018-05-24 15:50:06 -07001207 }
1208
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001209 if (!isConnected(*displayId)) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001210 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Already disconnected");
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001211 return {};
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001212 }
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001213
1214 // The display will later be destroyed by a call to HWComposer::disconnectDisplay. For now, mark
1215 // it as disconnected.
1216 mDisplayData.at(*displayId).hwcDisplay->setConnected(false);
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -04001217 mComposer->onHotplugDisconnect(hwcDisplayId);
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001218 return DisplayIdentificationInfo{.id = *displayId};
Steven Thomas6e8f7062017-11-22 14:15:29 -08001219}
1220
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001221void HWComposer::loadCapabilities() {
Peiyong Line9d809e2020-04-14 13:10:48 -07001222 static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001223 auto capabilities = mComposer->getCapabilities();
1224 for (auto capability : capabilities) {
Ady Abrahamde549d42022-01-26 19:19:17 -08001225 mCapabilities.emplace(capability);
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001226 }
1227}
1228
Sally Qibb866c12022-10-17 11:31:20 -07001229void HWComposer::loadOverlayProperties() {
1230 mComposer->getOverlaySupport(&mOverlayProperties);
1231}
1232
Kriti Dang674b9372022-11-18 10:58:44 +01001233void HWComposer::loadHdrConversionCapabilities() {
1234 const auto error = mComposer->getHdrConversionCapabilities(&mHdrConversionCapabilities);
1235 if (error != hal::Error::NONE) {
1236 ALOGE("Error in fetching HDR conversion capabilities %s", to_string(error).c_str());
1237 mHdrConversionCapabilities = {};
1238 }
1239}
1240
ramindani32cf0602022-03-02 02:30:29 +00001241status_t HWComposer::setIdleTimerEnabled(PhysicalDisplayId displayId,
1242 std::chrono::milliseconds timeout) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +00001243 SFTRACE_CALL();
ramindani32cf0602022-03-02 02:30:29 +00001244 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1245 const auto error = mDisplayData[displayId].hwcDisplay->setIdleTimerEnabled(timeout);
1246 if (error == hal::Error::UNSUPPORTED) {
1247 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1248 }
1249 if (error == hal::Error::BAD_PARAMETER) {
1250 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1251 }
1252 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1253 return NO_ERROR;
1254}
1255
ramindani06e518e2022-03-14 18:47:53 +00001256bool HWComposer::hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) const {
ramindani32cf0602022-03-02 02:30:29 +00001257 RETURN_IF_INVALID_DISPLAY(displayId, false);
ramindani06e518e2022-03-14 18:47:53 +00001258 return mDisplayData.at(displayId).hwcDisplay->hasDisplayIdleTimerCapability();
1259}
1260
1261Hwc2::AidlTransform HWComposer::getPhysicalDisplayOrientation(PhysicalDisplayId displayId) const {
Vishnu Nairbe0ad902024-06-27 23:38:43 +00001262 SFTRACE_CALL();
ramindani06e518e2022-03-14 18:47:53 +00001263 RETURN_IF_INVALID_DISPLAY(displayId, Hwc2::AidlTransform::NONE);
1264 Hwc2::AidlTransform outTransform;
1265 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
1266 const auto error = hwcDisplay->getPhysicalDisplayOrientation(&outTransform);
1267 RETURN_IF_HWC_ERROR(error, displayId, Hwc2::AidlTransform::NONE);
1268 return outTransform;
ramindani32cf0602022-03-02 02:30:29 +00001269}
1270
Lloyd Pique4603f3c2020-02-11 12:06:56 -08001271void HWComposer::loadLayerMetadataSupport() {
1272 mSupportedLayerGenericMetadata.clear();
1273
1274 std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo;
1275 const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo);
1276 if (error != hardware::graphics::composer::V2_4::Error::NONE) {
Ady Abraham3891cbe2021-03-29 11:29:31 -07001277 if (error != hardware::graphics::composer::V2_4::Error::UNSUPPORTED) {
1278 ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
1279 toString(error).c_str(), static_cast<int32_t>(error));
1280 }
Lloyd Pique4603f3c2020-02-11 12:06:56 -08001281 return;
1282 }
1283
1284 for (const auto& [name, mandatory] : supportedMetadataKeyInfo) {
1285 mSupportedLayerGenericMetadata.emplace(name, mandatory);
1286 }
1287}
1288
Lloyd Pique441d5042018-10-18 16:49:51 -07001289} // namespace impl
Dominik Laskowskif9750f22018-06-06 12:24:53 -07001290} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001291
1292// TODO(b/129481165): remove the #pragma below and fix conversion issues
1293#pragma clang diagnostic pop // ignored "-Wconversion"