blob: aefa7c355171f8fe9614c64bd3ab592bd506d997 [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
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Dan Stoza9e56aa02015-11-02 13:00:03 -080021// #define LOG_NDEBUG 0
22
23#undef LOG_TAG
24#define LOG_TAG "HWComposer"
Mathias Agopian2965b262012-04-08 15:13:32 -070025#define ATRACE_TAG ATRACE_TAG_GRAPHICS
26
Lloyd Pique66d68602019-02-13 14:23:31 -080027#include "HWComposer.h"
28
Marin Shalamanovf8c63722020-10-06 13:11:21 +020029#include <android-base/properties.h>
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080030#include <compositionengine/Output.h>
31#include <compositionengine/OutputLayer.h>
32#include <compositionengine/impl/OutputLayerCompositionState.h>
Leon Scroggins III959a7ff2023-02-07 11:24:25 -050033#include <ftl/concat.h>
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080034#include <log/log.h>
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070035#include <ui/DebugUtils.h>
Mathias Agopian921e6ac2012-07-23 23:11:29 -070036#include <ui/GraphicBuffer.h>
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080037#include <utils/Errors.h>
38#include <utils/Trace.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070039
Lloyd Pique66d68602019-02-13 14:23:31 -080040#include "../Layer.h" // needed only for debugging
Marin Shalamanovf8c63722020-10-06 13:11:21 +020041#include "../SurfaceFlingerProperties.h"
Lloyd Pique66d68602019-02-13 14:23:31 -080042#include "ComposerHal.h"
43#include "HWC2.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070044
Dominik Laskowskic1f18f62018-06-13 15:17:55 -070045#define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
46 ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
47
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070048#define LOG_DISPLAY_ERROR(displayId, msg) \
Dominik Laskowski34157762018-10-31 13:07:19 -070049 ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg)
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070050
Dominik Laskowski34157762018-10-31 13:07:19 -070051#define LOG_HWC_ERROR(what, error, displayId) \
52 ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \
53 to_string(displayId).c_str(), to_string(error).c_str(), static_cast<int32_t>(error))
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070054
55#define RETURN_IF_INVALID_DISPLAY(displayId, ...) \
56 do { \
Dominik Laskowski075d3172018-05-24 15:50:06 -070057 if (mDisplayData.count(displayId) == 0) { \
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070058 LOG_DISPLAY_ERROR(displayId, "Invalid display"); \
59 return __VA_ARGS__; \
60 } \
61 } while (false)
62
63#define RETURN_IF_HWC_ERROR_FOR(what, error, displayId, ...) \
64 do { \
Peiyong Line9d809e2020-04-14 13:10:48 -070065 if (error != hal::Error::NONE) { \
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070066 LOG_HWC_ERROR(what, error, displayId); \
67 return __VA_ARGS__; \
68 } \
69 } while (false)
70
71#define RETURN_IF_HWC_ERROR(error, displayId, ...) \
72 RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)
73
Kriti Dang674b9372022-11-18 10:58:44 +010074using aidl::android::hardware::graphics::common::HdrConversionCapability;
75using aidl::android::hardware::graphics::common::HdrConversionStrategy;
Ady Abrahamde549d42022-01-26 19:19:17 -080076using aidl::android::hardware::graphics::composer3::Capability;
77using aidl::android::hardware::graphics::composer3::DisplayCapability;
Peiyong Line9d809e2020-04-14 13:10:48 -070078namespace hal = android::hardware::graphics::composer::hal;
79
Marin Shalamanov6e840172020-12-14 22:13:28 +010080namespace android {
Peiyong Linbdd08cc2019-12-17 21:35:14 -080081
Lloyd Pique441d5042018-10-18 16:49:51 -070082HWComposer::~HWComposer() = default;
83
84namespace impl {
85
Marin Shalamanovf8c63722020-10-06 13:11:21 +020086HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
87 : mComposer(std::move(composer)),
Dominik Laskowski13948602021-03-08 20:48:28 -080088 mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))),
Marin Shalamanovf8c63722020-10-06 13:11:21 +020089 mUpdateDeviceProductInfoOnHotplugReconnect(
Dominik Laskowski13948602021-03-08 20:48:28 -080090 sysprop::update_device_product_info_on_hotplug_reconnect(false)) {}
Peiyong Linbdd08cc2019-12-17 21:35:14 -080091
92HWComposer::HWComposer(const std::string& composerServiceName)
Ady Abraham9fc28052021-10-14 17:21:38 -070093 : HWComposer(Hwc2::Composer::create(composerServiceName)) {}
Mathias Agopianbef42c52013-08-21 17:45:46 -070094
Dominik Laskowskib04f98a2018-11-07 21:07:16 -080095HWComposer::~HWComposer() {
96 mDisplayData.clear();
97}
Dan Stoza9e56aa02015-11-02 13:00:03 -080098
Yichi Chen3401b562022-01-17 15:42:35 +080099void HWComposer::setCallback(HWC2::ComposerCallback& callback) {
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800100 loadCapabilities();
101 loadLayerMetadataSupport();
Sally Qibb866c12022-10-17 11:31:20 -0700102 loadOverlayProperties();
Kriti Dang674b9372022-11-18 10:58:44 +0100103 loadHdrConversionCapabilities();
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800104
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800105 if (mRegisteredCallback) {
106 ALOGW("Callback already registered. Ignored extra registration attempt.");
107 return;
108 }
109 mRegisteredCallback = true;
Dominik Laskowskiebc8d3a2021-04-16 23:18:31 -0700110
Yichi Chen3401b562022-01-17 15:42:35 +0800111 mComposer->registerCallback(callback);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800112}
113
Peiyong Line9d809e2020-04-14 13:10:48 -0700114bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700115 DisplayIdentificationData* outData) const {
Peiyong Line9d809e2020-04-14 13:10:48 -0700116 const auto error = static_cast<hal::Error>(
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800117 mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
Peiyong Line9d809e2020-04-14 13:10:48 -0700118 if (error != hal::Error::NONE) {
119 if (error != hal::Error::UNSUPPORTED) {
Chia-I Wud0aff9d2018-06-21 13:39:09 +0800120 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
121 }
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700122 return false;
123 }
124 return true;
125}
126
Ady Abrahamde549d42022-01-26 19:19:17 -0800127bool HWComposer::hasCapability(Capability capability) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800128 return mCapabilities.count(capability) > 0;
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700129}
130
Ady Abrahamde549d42022-01-26 19:19:17 -0800131bool HWComposer::hasDisplayCapability(HalDisplayId displayId, DisplayCapability capability) const {
Dominik Laskowski1162e472020-04-02 19:02:47 -0700132 RETURN_IF_INVALID_DISPLAY(displayId, false);
Ady Abraham27fbcc72021-09-20 14:54:57 -0700133 return mDisplayData.at(displayId).hwcDisplay->hasCapability(capability);
Peiyong Lined531a32018-10-26 18:27:56 -0700134}
135
Peiyong Line9d809e2020-04-14 13:10:48 -0700136std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
137 hal::Connection connection) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100138 switch (connection) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700139 case hal::Connection::CONNECTED:
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100140 return onHotplugConnect(hwcDisplayId);
Peiyong Line9d809e2020-04-14 13:10:48 -0700141 case hal::Connection::DISCONNECTED:
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100142 return onHotplugDisconnect(hwcDisplayId);
Peiyong Line9d809e2020-04-14 13:10:48 -0700143 case hal::Connection::INVALID:
Dominik Laskowski075d3172018-05-24 15:50:06 -0700144 return {};
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700145 }
Andy McFaddenb0d1dd32012-09-10 14:08:09 -0700146}
147
Marin Shalamanovf8c63722020-10-06 13:11:21 +0200148bool HWComposer::updatesDeviceProductInfoOnHotplugReconnect() const {
149 return mUpdateDeviceProductInfoOnHotplugReconnect;
150}
151
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500152std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId,
153 nsecs_t timestamp) {
154 const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId);
155 if (!displayIdOpt) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700156 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500157 return {};
Jesse Hall1bd20e02012-08-29 10:47:52 -0700158 }
Jesse Hall1bd20e02012-08-29 10:47:52 -0700159
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500160 RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {});
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700161
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500162 auto& displayData = mDisplayData[*displayIdOpt];
Jesse Hall1bd20e02012-08-29 10:47:52 -0700163
Dan Stoza9e56aa02015-11-02 13:00:03 -0800164 {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800165 // There have been reports of HWCs that signal several vsync events
166 // with the same timestamp when turning the display off and on. This
167 // is a bug in the HWC implementation, but filter the extra events
168 // out here so they don't cause havoc downstream.
Dominik Laskowskidc2bb802022-09-28 16:02:59 -0400169 if (timestamp == displayData.lastPresentTimestamp) {
Dominik Laskowski34157762018-10-31 13:07:19 -0700170 ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500171 to_string(*displayIdOpt).c_str(), timestamp);
172 return {};
Dan Stoza9e56aa02015-11-02 13:00:03 -0800173 }
174
Dominik Laskowskidc2bb802022-09-28 16:02:59 -0400175 displayData.lastPresentTimestamp = timestamp;
Jesse Hall1c569c42013-04-05 13:44:52 -0700176 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800177
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500178 ATRACE_INT(ftl::Concat("HW_VSYNC_", displayIdOpt->value).c_str(),
179 displayData.vsyncTraceToggle);
Dominik Laskowski1af47932018-11-12 10:20:46 -0800180 displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800181
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500182 return displayIdOpt;
Jesse Hall1c569c42013-04-05 13:44:52 -0700183}
184
Dominik Laskowski13948602021-03-08 20:48:28 -0800185size_t HWComposer::getMaxVirtualDisplayCount() const {
186 return mComposer->getMaxVirtualDisplayCount();
187}
188
189size_t HWComposer::getMaxVirtualDisplayDimension() const {
190 return mMaxVirtualDisplayDimension;
191}
192
193bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size resolution,
Dominik Laskowski263eec42021-07-21 23:13:24 -0700194 ui::PixelFormat* format) {
Dominik Laskowski13948602021-03-08 20:48:28 -0800195 if (!resolution.isValid()) {
196 ALOGE("%s: Invalid resolution %dx%d", __func__, resolution.width, resolution.height);
197 return false;
Fabien Sanglarde29055f2017-03-08 11:36:46 -0800198 }
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200199
Dominik Laskowski13948602021-03-08 20:48:28 -0800200 const uint32_t width = static_cast<uint32_t>(resolution.width);
201 const uint32_t height = static_cast<uint32_t>(resolution.height);
202
203 if (mMaxVirtualDisplayDimension > 0 &&
204 (width > mMaxVirtualDisplayDimension || height > mMaxVirtualDisplayDimension)) {
205 ALOGE("%s: Resolution %ux%u exceeds maximum dimension %zu", __func__, width, height,
206 mMaxVirtualDisplayDimension);
207 return false;
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200208 }
209
Dominik Laskowski13948602021-03-08 20:48:28 -0800210 hal::HWDisplayId hwcDisplayId;
Peiyong Line9d809e2020-04-14 13:10:48 -0700211 const auto error = static_cast<hal::Error>(
Dominik Laskowski263eec42021-07-21 23:13:24 -0700212 mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
Dominik Laskowski13948602021-03-08 20:48:28 -0800213 RETURN_IF_HWC_ERROR_FOR("createVirtualDisplay", error, displayId, false);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800214
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800215 auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
Peiyong Line9d809e2020-04-14 13:10:48 -0700216 hwcDisplayId, hal::DisplayType::VIRTUAL);
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800217 display->setConnected(true);
Dominik Laskowski13948602021-03-08 20:48:28 -0800218 auto& displayData = mDisplayData[displayId];
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800219 displayData.hwcDisplay = std::move(display);
Dominik Laskowski13948602021-03-08 20:48:28 -0800220 return true;
Mathias Agopiane60b0682012-08-21 23:34:09 -0700221}
222
Marin Shalamanova524a092020-07-27 21:39:55 +0200223void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,
224 PhysicalDisplayId displayId) {
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100225 mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
226
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700227 if (!mPrimaryHwcDisplayId) {
228 mPrimaryHwcDisplayId = hwcDisplayId;
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100229 }
230
231 auto& displayData = mDisplayData[displayId];
232 auto newDisplay =
233 std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
Peiyong Line9d809e2020-04-14 13:10:48 -0700234 hal::DisplayType::PHYSICAL);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100235 newDisplay->setConnected(true);
236 displayData.hwcDisplay = std::move(newDisplay);
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100237}
238
239int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
Marin Shalamanov045b7002021-01-07 16:56:24 +0100240 hal::Attribute attribute) const {
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100241 int32_t value = 0;
242 auto error = static_cast<hal::Error>(
243 mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
244
245 RETURN_IF_HWC_ERROR_FOR("getDisplayAttribute", error, *toPhysicalDisplayId(hwcDisplayId), -1);
246 return value;
247}
248
Lloyd Pique1b33fc32021-05-07 14:36:58 -0700249std::shared_ptr<HWC2::Layer> HWComposer::createLayer(HalDisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700250 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
251
Lloyd Pique1b33fc32021-05-07 14:36:58 -0700252 auto expected = mDisplayData[displayId].hwcDisplay->createLayer();
253 if (!expected.has_value()) {
254 auto error = std::move(expected).error();
255 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
256 }
257 return std::move(expected).value();
Steven Thomas94e35b92017-07-26 18:48:28 -0700258}
259
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200260bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
Dominik Laskowskif2ddca62022-08-17 12:08:07 -0700261 return mDisplayData.count(displayId) && mDisplayData.at(displayId).hwcDisplay->isConnected();
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700262}
263
Marin Shalamanov045b7002021-01-07 16:56:24 +0100264std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700265 RETURN_IF_INVALID_DISPLAY(displayId, {});
266
Marin Shalamanov045b7002021-01-07 16:56:24 +0100267 const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
ramindani0cd1d8d2023-06-13 13:43:23 -0700268
269 if (mComposer->getDisplayConfigurationsSupported()) {
270 return getModesFromDisplayConfigurations(hwcDisplayId);
271 }
272
273 return getModesFromLegacyDisplayConfigs(hwcDisplayId);
274}
275
276std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromDisplayConfigurations(
277 uint64_t hwcDisplayId) const {
278 std::vector<hal::DisplayConfiguration> configs;
279 auto error =
280 static_cast<hal::Error>(mComposer->getDisplayConfigurations(hwcDisplayId, &configs));
281 RETURN_IF_HWC_ERROR_FOR("getDisplayConfigurations", error, *toPhysicalDisplayId(hwcDisplayId),
282 {});
283
284 std::vector<HWCDisplayMode> modes;
285 modes.reserve(configs.size());
286 for (auto config : configs) {
287 auto hwcMode = HWCDisplayMode{
288 .hwcId = static_cast<hal::HWConfigId>(config.configId),
289 .width = config.width,
290 .height = config.height,
291 .vsyncPeriod = config.vsyncPeriod,
292 .configGroup = config.configGroup,
293 };
294
295 if (config.dpi) {
296 hwcMode.dpiX = config.dpi->x;
297 hwcMode.dpiY = config.dpi->y;
298 }
299
300 modes.push_back(hwcMode);
301 }
302
303 return modes;
304}
305
306std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromLegacyDisplayConfigs(
307 uint64_t hwcDisplayId) const {
Marin Shalamanov045b7002021-01-07 16:56:24 +0100308 std::vector<hal::HWConfigId> configIds;
309 auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
310 RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
311
312 std::vector<HWCDisplayMode> modes;
313 modes.reserve(configIds.size());
314 for (auto configId : configIds) {
ramindani0cd1d8d2023-06-13 13:43:23 -0700315 auto hwcMode = HWCDisplayMode{
Marin Shalamanov045b7002021-01-07 16:56:24 +0100316 .hwcId = configId,
317 .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
318 .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
319 .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
Marin Shalamanov045b7002021-01-07 16:56:24 +0100320 .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
ramindani0cd1d8d2023-06-13 13:43:23 -0700321 };
Marin Shalamanov045b7002021-01-07 16:56:24 +0100322
ramindani0cd1d8d2023-06-13 13:43:23 -0700323 const int32_t dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X);
324 const int32_t dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y);
325 if (dpiX != -1) {
326 hwcMode.dpiX = static_cast<float>(dpiX) / 1000.f;
327 }
328 if (dpiY != -1) {
329 hwcMode.dpiY = static_cast<float>(dpiY) / 1000.f;
330 }
331
332 modes.push_back(hwcMode);
333 }
Marin Shalamanov045b7002021-01-07 16:56:24 +0100334 return modes;
Mathias Agopianda27af92012-09-13 18:17:13 -0700335}
336
Marin Shalamanov045b7002021-01-07 16:56:24 +0100337std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
338 RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100339 const auto hwcId = *fromPhysicalDisplayId(displayId);
Dominik Laskowskie2c5b0a2022-08-10 14:53:53 -0700340
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100341 hal::HWConfigId configId;
Dominik Laskowskie2c5b0a2022-08-10 14:53:53 -0700342 const auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100343
Dominik Laskowskie2c5b0a2022-08-10 14:53:53 -0700344 RETURN_IF_HWC_ERROR_FOR("getActiveConfig", error, displayId, std::nullopt);
Marin Shalamanov045b7002021-01-07 16:56:24 +0100345 return configId;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700346}
347
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800348// Composer 2.4
349
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100350ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
351 RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal);
Dominik Laskowski55c85402020-01-21 16:25:47 -0800352 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
353
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100354 ui::DisplayConnectionType type;
Dominik Laskowski55c85402020-01-21 16:25:47 -0800355 const auto error = hwcDisplay->getConnectionType(&type);
356
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700357 const auto FALLBACK_TYPE = hwcDisplay->getId() == mPrimaryHwcDisplayId
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100358 ? ui::DisplayConnectionType::Internal
359 : ui::DisplayConnectionType::External;
Dominik Laskowski55c85402020-01-21 16:25:47 -0800360
361 RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
362 return type;
363}
364
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200365bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const {
Dominik Laskowski55c85402020-01-21 16:25:47 -0800366 RETURN_IF_INVALID_DISPLAY(displayId, false);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800367 return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
368}
369
Marin Shalamanov045b7002021-01-07 16:56:24 +0100370status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId,
371 nsecs_t* outVsyncPeriod) const {
Dominik Laskowski55c85402020-01-21 16:25:47 -0800372 RETURN_IF_INVALID_DISPLAY(displayId, 0);
373
Marin Shalamanov045b7002021-01-07 16:56:24 +0100374 if (!isVsyncPeriodSwitchSupported(displayId)) {
375 return INVALID_OPERATION;
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700376 }
Marin Shalamanov045b7002021-01-07 16:56:24 +0100377 const auto hwcId = *fromPhysicalDisplayId(displayId);
378 Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
379 auto error =
380 static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
381 RETURN_IF_HWC_ERROR(error, displayId, 0);
382 *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
383 return NO_ERROR;
Lloyd Pique3c085a02018-05-09 19:38:32 -0700384}
385
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200386std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700387 RETURN_IF_INVALID_DISPLAY(displayId, {});
388
Peiyong Linfd997e02018-03-28 15:29:00 -0700389 std::vector<ui::ColorMode> modes;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700390 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700391 RETURN_IF_HWC_ERROR(error, displayId, {});
Courtney Goeltzenleuchterfad9d8c2016-06-23 11:49:50 -0600392 return modes;
393}
394
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200395status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700396 ui::RenderIntent renderIntent) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700397 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Michael Wright28f24d02016-07-12 13:30:53 -0700398
399 auto& displayData = mDisplayData[displayId];
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700400 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700401 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
402 decodeRenderIntent(renderIntent) + ")")
403 .c_str(),
404 error, displayId, UNKNOWN_ERROR);
Michael Wright28f24d02016-07-12 13:30:53 -0700405
406 return NO_ERROR;
407}
408
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200409void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700410 RETURN_IF_INVALID_DISPLAY(displayId);
411 auto& displayData = mDisplayData[displayId];
412
Dan Stoza9e56aa02015-11-02 13:00:03 -0800413 // NOTE: we use our own internal lock here because we have to call
414 // into the HWC with the lock held, and we want to make sure
415 // that even if HWC blocks (which it shouldn't), it won't
416 // affect other threads.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800417 std::lock_guard lock(displayData.vsyncEnabledLock);
418 if (enabled == displayData.vsyncEnabled) {
419 return;
Colin Cross10fbdb62012-07-12 17:56:34 -0700420 }
Dominik Laskowski1af47932018-11-12 10:20:46 -0800421
422 ATRACE_CALL();
423 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
424 RETURN_IF_HWC_ERROR(error, displayId);
425
426 displayData.vsyncEnabled = enabled;
427
Leon Scroggins III959a7ff2023-02-07 11:24:25 -0500428 ATRACE_INT(ftl::Concat("HW_VSYNC_ON_", displayId.value).c_str(),
429 enabled == hal::Vsync::ENABLE ? 1 : 0);
Colin Cross10fbdb62012-07-12 17:56:34 -0700430}
431
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200432status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700433 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
434 ui::Dataspace dataspace) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700435 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Jesse Hall851cfe82013-03-20 13:44:00 -0700436
Dominik Laskowski34157762018-10-31 13:07:19 -0700437 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
Dan Stoza9e56aa02015-11-02 13:00:03 -0800438 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Daniel Nicoara1f42e3a2017-04-10 13:27:32 -0400439 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700440 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
Jesse Hall851cfe82013-03-20 13:44:00 -0700441 return NO_ERROR;
442}
443
Lloyd Pique66d68602019-02-13 14:23:31 -0800444status_t HWComposer::getDeviceCompositionChanges(
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200445 HalDisplayId displayId, bool frameUsesClientComposition,
Ady Abrahamf1db8032023-03-24 17:52:34 -0700446 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime,
447 nsecs_t expectedPresentTime,
Lloyd Pique66d68602019-02-13 14:23:31 -0800448 std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800449 ATRACE_CALL();
450
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700451 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800452
453 auto& displayData = mDisplayData[displayId];
454 auto& hwcDisplay = displayData.hwcDisplay;
455 if (!hwcDisplay->isConnected()) {
456 return NO_ERROR;
457 }
458
459 uint32_t numTypes = 0;
460 uint32_t numRequests = 0;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700461
Peiyong Line9d809e2020-04-14 13:10:48 -0700462 hal::Error error = hal::Error::NONE;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700463
Ady Abrahamec7aa8a2021-06-28 12:37:09 -0700464 // First try to skip validate altogether. We can do that when
465 // 1. The previous frame has not been presented yet or already passed the
466 // earliest time to present. Otherwise, we may present a frame too early.
467 // 2. There is no client composition. Otherwise, we first need to render the
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700468 // client target buffer.
Ady Abraham43065bd2021-12-10 17:22:15 -0800469 const bool canSkipValidate = [&] {
470 // We must call validate if we have client composition
471 if (frameUsesClientComposition) {
472 return false;
473 }
474
475 // If composer supports getting the expected present time, we can skip
476 // as composer will make sure to prevent early presentation
Ady Abrahamf1db8032023-03-24 17:52:34 -0700477 if (!earliestPresentTime) {
Ady Abraham43065bd2021-12-10 17:22:15 -0800478 return true;
479 }
480
481 // composer doesn't support getting the expected present time. We can only
482 // skip validate if we know that we are not going to present early.
Ady Abrahamf1db8032023-03-24 17:52:34 -0700483 return std::chrono::steady_clock::now() >= *earliestPresentTime;
Ady Abraham43065bd2021-12-10 17:22:15 -0800484 }();
485
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700486 displayData.validateWasSkipped = false;
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700487 if (canSkipValidate) {
Dominik Laskowski1af47932018-11-12 10:20:46 -0800488 sp<Fence> outPresentFence;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700489 uint32_t state = UINT32_MAX;
Ady Abraham43065bd2021-12-10 17:22:15 -0800490 error = hwcDisplay->presentOrValidate(expectedPresentTime, &numTypes, &numRequests,
491 &outPresentFence, &state);
Peiyong Line9d809e2020-04-14 13:10:48 -0700492 if (!hasChangesError(error)) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700493 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700494 }
495 if (state == 1) { //Present Succeeded.
Steven Thomas94e35b92017-07-26 18:48:28 -0700496 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700497 error = hwcDisplay->getReleaseFences(&releaseFences);
498 displayData.releaseFences = std::move(releaseFences);
499 displayData.lastPresentFence = outPresentFence;
500 displayData.validateWasSkipped = true;
501 displayData.presentError = error;
502 return NO_ERROR;
503 }
504 // Present failed but Validate ran.
505 } else {
Ady Abraham43065bd2021-12-10 17:22:15 -0800506 error = hwcDisplay->validate(expectedPresentTime, &numTypes, &numRequests);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700507 }
508 ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
Peiyong Line9d809e2020-04-14 13:10:48 -0700509 if (!hasChangesError(error)) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700510 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800511 }
512
Lloyd Pique66d68602019-02-13 14:23:31 -0800513 android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800514 changedTypes.reserve(numTypes);
515 error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700516 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800517
Peiyong Line9d809e2020-04-14 13:10:48 -0700518 auto displayRequests = static_cast<hal::DisplayRequest>(0);
Lloyd Pique66d68602019-02-13 14:23:31 -0800519 android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800520 layerRequests.reserve(numRequests);
Lloyd Pique66d68602019-02-13 14:23:31 -0800521 error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700522 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800523
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700524 DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
Alec Mouri85065692022-03-18 00:58:26 +0000525 error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800526
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700527 outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
528 std::move(layerRequests),
Alec Mouri85065692022-03-18 00:58:26 +0000529 std::move(clientTargetProperty)});
Dan Stoza9e56aa02015-11-02 13:00:03 -0800530 error = hwcDisplay->acceptChanges();
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700531 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800532
533 return NO_ERROR;
534}
535
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200536sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700537 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700538 return mDisplayData.at(displayId).lastPresentFence;
Jesse Hall851cfe82013-03-20 13:44:00 -0700539}
540
Dominik Laskowskidc2bb802022-09-28 16:02:59 -0400541nsecs_t HWComposer::getPresentTimestamp(PhysicalDisplayId displayId) const {
542 RETURN_IF_INVALID_DISPLAY(displayId, 0);
543 return mDisplayData.at(displayId).lastPresentTimestamp;
544}
545
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200546sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700547 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Tim Murray2d3f8b82019-12-04 16:24:17 -0800548 const auto& displayFences = mDisplayData.at(displayId).releaseFences;
549 auto fence = displayFences.find(layer);
550 if (fence == displayFences.end()) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800551 ALOGV("getLayerReleaseFence: Release fence not found");
552 return Fence::NO_FENCE;
Riley Andrews03414a12014-07-01 14:22:59 -0700553 }
Tim Murray2d3f8b82019-12-04 16:24:17 -0800554 return fence->second;
Riley Andrews03414a12014-07-01 14:22:59 -0700555}
556
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700557status_t HWComposer::presentAndGetReleaseFences(
Ady Abrahamf1db8032023-03-24 17:52:34 -0700558 HalDisplayId displayId,
559 std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800560 ATRACE_CALL();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700561
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700562 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Pablo Ceballosd814cf22015-09-11 14:37:39 -0700563
Dan Stoza9e56aa02015-11-02 13:00:03 -0800564 auto& displayData = mDisplayData[displayId];
565 auto& hwcDisplay = displayData.hwcDisplay;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700566
567 if (displayData.validateWasSkipped) {
Chia-I Wuae5a6b82017-10-10 09:09:22 -0700568 // explicitly flush all pending commands
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -0400569 auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800570 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700571 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700572 return NO_ERROR;
573 }
574
Ady Abrahamf1db8032023-03-24 17:52:34 -0700575 if (earliestPresentTime) {
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700576 ATRACE_NAME("wait for earliest present time");
Ady Abrahamf1db8032023-03-24 17:52:34 -0700577 std::this_thread::sleep_until(*earliestPresentTime);
Ady Abrahamb42cdc12021-05-11 14:31:26 -0700578 }
579
Fabien Sanglard11d0fc32016-12-01 15:43:01 -0800580 auto error = hwcDisplay->present(&displayData.lastPresentFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700581 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700582
Steven Thomas94e35b92017-07-26 18:48:28 -0700583 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800584 error = hwcDisplay->getReleaseFences(&releaseFences);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700585 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800586
587 displayData.releaseFences = std::move(releaseFences);
588
589 return NO_ERROR;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700590}
591
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200592status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700593 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
594
Peiyong Line9d809e2020-04-14 13:10:48 -0700595 if (mode == hal::PowerMode::OFF) {
596 setVsyncEnabled(displayId, hal::Vsync::DISABLE);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800597 }
598
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700599 const auto& displayData = mDisplayData[displayId];
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700600 auto& hwcDisplay = displayData.hwcDisplay;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800601 switch (mode) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700602 case hal::PowerMode::OFF:
603 case hal::PowerMode::ON:
Dan Stoza9e56aa02015-11-02 13:00:03 -0800604 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
605 {
606 auto error = hwcDisplay->setPowerMode(mode);
Peiyong Line9d809e2020-04-14 13:10:48 -0700607 if (error != hal::Error::NONE) {
608 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
609 displayId);
Peiyong Lin306e4992018-05-07 16:18:22 -0700610 }
Mathias Agopianda27af92012-09-13 18:17:13 -0700611 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800612 break;
Peiyong Line9d809e2020-04-14 13:10:48 -0700613 case hal::PowerMode::DOZE:
614 case hal::PowerMode::DOZE_SUSPEND:
Dan Stoza9e56aa02015-11-02 13:00:03 -0800615 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
616 {
617 bool supportsDoze = false;
618 auto error = hwcDisplay->supportsDoze(&supportsDoze);
Peiyong Line9d809e2020-04-14 13:10:48 -0700619 if (error != hal::Error::NONE) {
Peiyong Lin306e4992018-05-07 16:18:22 -0700620 LOG_HWC_ERROR("supportsDoze", error, displayId);
621 }
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700622
Dan Stoza9e56aa02015-11-02 13:00:03 -0800623 if (!supportsDoze) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700624 mode = hal::PowerMode::ON;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800625 }
626
627 error = hwcDisplay->setPowerMode(mode);
Peiyong Line9d809e2020-04-14 13:10:48 -0700628 if (error != hal::Error::NONE) {
629 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
630 displayId);
Peiyong Lin306e4992018-05-07 16:18:22 -0700631 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800632 }
633 break;
634 default:
635 ALOGV("setPowerMode: Not calling HWC");
636 break;
Mathias Agopianda27af92012-09-13 18:17:13 -0700637 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800638
639 return NO_ERROR;
640}
641
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100642status_t HWComposer::setActiveModeWithConstraints(
Marin Shalamanov12c9e5a2021-01-07 00:25:35 +0100643 PhysicalDisplayId displayId, hal::HWConfigId hwcModeId,
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200644 const hal::VsyncPeriodChangeConstraints& constraints,
Peiyong Line9d809e2020-04-14 13:10:48 -0700645 hal::VsyncPeriodChangeTimeline* outTimeline) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700646 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800647
Marin Shalamanov12c9e5a2021-01-07 00:25:35 +0100648 auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
649 constraints,
650 outTimeline);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700651 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800652 return NO_ERROR;
653}
654
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200655status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700656 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700657
658 auto& displayData = mDisplayData[displayId];
Ady Abrahamdc011a92021-12-21 14:06:44 -0800659 auto error = displayData.hwcDisplay->setColorTransform(transform);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700660 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700661 return NO_ERROR;
662}
663
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200664void HWComposer::disconnectDisplay(HalDisplayId displayId) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700665 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800666 auto& displayData = mDisplayData[displayId];
Dominik Laskowski7e045462018-05-30 13:02:02 -0700667 const auto hwcDisplayId = displayData.hwcDisplay->getId();
Dominik Laskowski075d3172018-05-24 15:50:06 -0700668
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800669 mPhysicalDisplayIdMap.erase(hwcDisplayId);
670 mDisplayData.erase(displayId);
Marin Shalamanov8b196592021-08-09 16:24:42 +0200671
672 // Reset the primary display ID if we're disconnecting it.
673 // This way isHeadless() will return false, which is necessary
674 // because getPrimaryDisplayId() will crash.
675 if (mPrimaryHwcDisplayId == hwcDisplayId) {
676 mPrimaryHwcDisplayId.reset();
677 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800678}
679
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200680status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700681 const sp<GraphicBuffer>& buffer) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700682 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700683 const auto& displayData = mDisplayData[displayId];
Dan Stoza9e56aa02015-11-02 13:00:03 -0800684
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700685 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700686 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800687 return NO_ERROR;
688}
689
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200690void HWComposer::clearReleaseFences(HalDisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700691 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800692 mDisplayData[displayId].releaseFences.clear();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700693}
694
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200695status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700696 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stozac4f471e2016-03-24 09:31:08 -0700697
698 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Peiyong Lin62665892018-04-16 11:07:44 -0700699 auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700700 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Peiyong Lin62665892018-04-16 11:07:44 -0700701 return NO_ERROR;
Dan Stozac4f471e2016-03-24 09:31:08 -0700702}
703
Sally Qibb866c12022-10-17 11:31:20 -0700704const aidl::android::hardware::graphics::composer3::OverlayProperties&
705HWComposer::getOverlaySupport() const {
706 return mOverlayProperties;
Sally Qi0cbd08b2022-08-17 12:12:28 -0700707}
708
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200709int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700710 RETURN_IF_INVALID_DISPLAY(displayId, 0);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700711 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
Peiyong Lin0ac5f4e2018-04-19 22:06:34 -0700712}
713
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200714std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700715 ui::ColorMode colorMode) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700716 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700717
718 std::vector<ui::RenderIntent> renderIntents;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700719 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700720 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700721 return renderIntents;
722}
723
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200724mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700725 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700726
727 mat4 matrix;
728 auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
729 &matrix);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700730 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700731 return matrix;
732}
733
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200734status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId,
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700735 ui::PixelFormat* outFormat,
736 ui::Dataspace* outDataspace,
737 uint8_t* outComponentMask) {
738 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
739 const auto error =
740 mDisplayData[displayId]
741 .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
742 outComponentMask);
Peiyong Line9d809e2020-04-14 13:10:48 -0700743 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700744 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
745 return NO_ERROR;
746}
747
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200748status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled,
Kevin DuBois74e53772018-11-19 10:52:38 -0800749 uint8_t componentMask, uint64_t maxFrames) {
750 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
751 const auto error =
752 mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
753 componentMask,
754 maxFrames);
755
Peiyong Line9d809e2020-04-14 13:10:48 -0700756 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
757 if (error == hal::Error::BAD_PARAMETER) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
Kevin DuBois74e53772018-11-19 10:52:38 -0800758 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
759 return NO_ERROR;
760}
761
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200762status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames,
Kevin DuBois1d4249a2018-08-29 10:45:14 -0700763 uint64_t timestamp, DisplayedFrameStats* outStats) {
764 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
765 const auto error =
766 mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
767 outStats);
768 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
769 return NO_ERROR;
770}
771
Dominik Laskowskib17c6212022-05-09 09:36:19 -0700772ftl::Future<status_t> HWComposer::setDisplayBrightness(
Alec Mouri4d8a05d2022-03-23 18:14:26 +0000773 PhysicalDisplayId displayId, float brightness, float brightnessNits,
Alec Mouricdf16792021-12-10 13:16:06 -0800774 const Hwc2::Composer::DisplayBrightnessOptions& options) {
Dominik Laskowski4e2b71f2020-11-10 15:05:32 -0800775 RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX));
Dominik Laskowski5690bde2020-04-23 19:04:22 -0700776 auto& display = mDisplayData[displayId].hwcDisplay;
777
Dominik Laskowskib17c6212022-05-09 09:36:19 -0700778 return display->setDisplayBrightness(brightness, brightnessNits, options)
Dominik Laskowski5690bde2020-04-23 19:04:22 -0700779 .then([displayId](hal::Error error) -> status_t {
780 if (error == hal::Error::UNSUPPORTED) {
781 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
782 }
783 if (error == hal::Error::BAD_PARAMETER) {
784 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
785 }
786 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
787 return NO_ERROR;
788 });
Dan Gittik57e63c52019-01-18 16:37:54 +0000789}
790
Matt Buckley50c44062022-01-17 20:48:10 +0000791bool HWComposer::getValidateSkipped(HalDisplayId displayId) const {
792 if (mDisplayData.count(displayId) == 0) {
793 return false;
794 }
795 return mDisplayData.at(displayId).validateWasSkipped;
796}
797
Kriti Dang7defaf32021-11-15 11:55:43 +0100798status_t HWComposer::setBootDisplayMode(PhysicalDisplayId displayId,
799 hal::HWConfigId displayModeId) {
800 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
801 const auto error = mDisplayData[displayId].hwcDisplay->setBootDisplayConfig(displayModeId);
802 if (error == hal::Error::UNSUPPORTED) {
803 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
804 }
805 if (error == hal::Error::BAD_PARAMETER) {
806 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
807 }
808 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
809 return NO_ERROR;
810}
811
812status_t HWComposer::clearBootDisplayMode(PhysicalDisplayId displayId) {
813 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
814 const auto error = mDisplayData[displayId].hwcDisplay->clearBootDisplayConfig();
815 if (error == hal::Error::UNSUPPORTED) {
816 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
817 }
818 if (error == hal::Error::BAD_PARAMETER) {
819 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
820 }
821 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
822 return NO_ERROR;
823}
824
Kriti Dang16ca2972022-02-01 20:07:03 +0100825std::optional<hal::HWConfigId> HWComposer::getPreferredBootDisplayMode(
826 PhysicalDisplayId displayId) {
827 RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
828 hal::HWConfigId displayModeId;
Kriti Dang7defaf32021-11-15 11:55:43 +0100829 const auto error =
830 mDisplayData[displayId].hwcDisplay->getPreferredBootDisplayConfig(&displayModeId);
Kriti Dang16ca2972022-02-01 20:07:03 +0100831 if (error != hal::Error::NONE) {
832 LOG_DISPLAY_ERROR(displayId, to_string(error).c_str());
833 return std::nullopt;
Kriti Dang7defaf32021-11-15 11:55:43 +0100834 }
Kriti Dang7defaf32021-11-15 11:55:43 +0100835 return displayModeId;
836}
837
Kriti Dang674b9372022-11-18 10:58:44 +0100838std::vector<HdrConversionCapability> HWComposer::getHdrConversionCapabilities() const {
839 return mHdrConversionCapabilities;
840}
841
Kriti Dangd432bb52023-02-09 18:21:04 +0100842status_t HWComposer::setHdrConversionStrategy(
843 HdrConversionStrategy hdrConversionStrategy,
844 aidl::android::hardware::graphics::common::Hdr* outPreferredHdrOutputType) {
845 const auto error =
846 mComposer->setHdrConversionStrategy(hdrConversionStrategy, outPreferredHdrOutputType);
Kriti Dang674b9372022-11-18 10:58:44 +0100847 if (error != hal::Error::NONE) {
848 ALOGE("Error in setting HDR conversion strategy %s", to_string(error).c_str());
Kriti Dangd432bb52023-02-09 18:21:04 +0100849 return INVALID_OPERATION;
Kriti Dang674b9372022-11-18 10:58:44 +0100850 }
851 return NO_ERROR;
852}
853
ramindanib2158ee2023-02-13 20:29:59 -0800854status_t HWComposer::setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId displayId,
855 bool enabled) {
856 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
857 const auto error =
858 mComposer->setRefreshRateChangedCallbackDebugEnabled(mDisplayData[displayId]
859 .hwcDisplay->getId(),
860 enabled);
861 if (error != hal::Error::NONE) {
862 ALOGE("Error in setting refresh refresh rate change callback debug enabled %s",
863 to_string(error).c_str());
864 return INVALID_OPERATION;
865 }
866 return NO_ERROR;
867}
868
Leon Scroggins IIIe7c51c62022-02-01 15:53:54 -0500869status_t HWComposer::getDisplayDecorationSupport(
870 PhysicalDisplayId displayId,
871 std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
872 support) {
873 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
874 const auto error = mDisplayData[displayId].hwcDisplay->getDisplayDecorationSupport(support);
875 if (error == hal::Error::UNSUPPORTED) {
876 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
877 }
878 if (error == hal::Error::BAD_PARAMETER) {
879 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
880 }
881 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
882 return NO_ERROR;
883}
884
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200885status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100886 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
887 const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
Peiyong Line9d809e2020-04-14 13:10:48 -0700888 if (error == hal::Error::UNSUPPORTED) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100889 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
890 }
Peiyong Line9d809e2020-04-14 13:10:48 -0700891 if (error == hal::Error::BAD_PARAMETER) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100892 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
893 }
894 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
895 return NO_ERROR;
896}
897
898status_t HWComposer::getSupportedContentTypes(
Dominik Laskowski6c7b36e2022-03-03 08:27:58 -0800899 PhysicalDisplayId displayId,
900 std::vector<hal::ContentType>* outSupportedContentTypes) const {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100901 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dominik Laskowski6c7b36e2022-03-03 08:27:58 -0800902 const auto error = mDisplayData.at(displayId).hwcDisplay->getSupportedContentTypes(
903 outSupportedContentTypes);
Galia Peycheva5492cb52019-10-30 14:13:16 +0100904
905 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
906
907 return NO_ERROR;
908}
909
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200910status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100911 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
912 const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
Peiyong Line9d809e2020-04-14 13:10:48 -0700913 if (error == hal::Error::UNSUPPORTED) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100914 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
915 }
Peiyong Line9d809e2020-04-14 13:10:48 -0700916 if (error == hal::Error::BAD_PARAMETER) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100917 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
918 }
919 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
920
921 return NO_ERROR;
922}
923
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800924const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
925 return mSupportedLayerGenericMetadata;
926}
927
Yiwei Zhang5434a782018-12-05 18:06:32 -0800928void HWComposer::dump(std::string& result) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800929 result.append(mComposer->dumpDebugInfo());
Mathias Agopian83727852010-09-23 18:13:21 -0700930}
931
Marin Shalamanova524a092020-07-27 21:39:55 +0200932std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
933 hal::HWDisplayId hwcDisplayId) const {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700934 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
935 it != mPhysicalDisplayIdMap.end()) {
936 return it->second;
937 }
938 return {};
939}
940
Marin Shalamanova524a092020-07-27 21:39:55 +0200941std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
942 PhysicalDisplayId displayId) const {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700943 if (const auto it = mDisplayData.find(displayId); it != mDisplayData.end()) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700944 return it->second.hwcDisplay->getId();
945 }
946 return {};
947}
948
Peiyong Line9d809e2020-04-14 13:10:48 -0700949bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100950 bool hasDisplayIdentificationData) const {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100951 if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700952 ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
953 hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100954 return true;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700955 }
956
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700957 // Legacy mode only supports IDs LEGACY_DISPLAY_TYPE_PRIMARY and LEGACY_DISPLAY_TYPE_EXTERNAL.
958 if (!mHasMultiDisplaySupport && mPhysicalDisplayIdMap.size() == 2) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700959 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100960 return true;
961 }
962
963 return false;
964}
965
Peiyong Line9d809e2020-04-14 13:10:48 -0700966std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
967 hal::HWDisplayId hwcDisplayId) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100968 std::optional<DisplayIdentificationInfo> info;
969 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
970 info = DisplayIdentificationInfo{.id = *displayId,
971 .name = std::string(),
972 .deviceProductInfo = std::nullopt};
Marin Shalamanovf8c63722020-10-06 13:11:21 +0200973 if (mUpdateDeviceProductInfoOnHotplugReconnect) {
974 uint8_t port;
975 DisplayIdentificationData data;
976 getDisplayIdentificationData(hwcDisplayId, &port, &data);
977 if (auto newInfo = parseDisplayIdentificationData(port, data)) {
978 info->deviceProductInfo = std::move(newInfo->deviceProductInfo);
979 } else {
980 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
981 }
982 }
Dominik Laskowski075d3172018-05-24 15:50:06 -0700983 } else {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100984 uint8_t port;
985 DisplayIdentificationData data;
986 const bool hasDisplayIdentificationData =
987 getDisplayIdentificationData(hwcDisplayId, &port, &data);
988 if (mPhysicalDisplayIdMap.empty()) {
989 mHasMultiDisplaySupport = hasDisplayIdentificationData;
990 ALOGI("Switching to %s multi-display mode",
991 mHasMultiDisplaySupport ? "generalized" : "legacy");
992 }
993
994 if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
995 return {};
996 }
997
998 info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -0700999 const bool isPrimary = !mPrimaryHwcDisplayId;
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001000 if (mHasMultiDisplaySupport) {
1001 if (const auto info = parseDisplayIdentificationData(port, data)) {
1002 return *info;
1003 }
1004 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
1005 } else {
1006 ALOGW_IF(hasDisplayIdentificationData,
1007 "Ignoring identification data for display %" PRIu64, hwcDisplayId);
Peiyong Lin65248e02020-04-18 21:15:07 -07001008 port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001009 }
1010
Marin Shalamanova524a092020-07-27 21:39:55 +02001011 return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001012 .name = isPrimary ? "Primary display"
1013 : "Secondary display",
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001014 .deviceProductInfo = std::nullopt};
1015 }();
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -04001016
1017 mComposer->onHotplugConnect(hwcDisplayId);
Dominik Laskowski075d3172018-05-24 15:50:06 -07001018 }
1019
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001020 if (!isConnected(info->id)) {
1021 allocatePhysicalDisplay(hwcDisplayId, info->id);
1022 }
1023 return info;
1024}
1025
1026std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
Peiyong Line9d809e2020-04-14 13:10:48 -07001027 hal::HWDisplayId hwcDisplayId) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001028 LOG_ALWAYS_FATAL_IF(hwcDisplayId == mPrimaryHwcDisplayId,
1029 "Primary display cannot be disconnected.");
1030
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001031 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
1032 if (!displayId) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001033 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001034 return {};
Dominik Laskowski075d3172018-05-24 15:50:06 -07001035 }
1036
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001037 if (!isConnected(*displayId)) {
Dominik Laskowskif8db0f02021-04-19 11:05:25 -07001038 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Already disconnected");
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001039 return {};
Marin Shalamanovbdd59152020-02-14 15:30:06 +01001040 }
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001041
1042 // The display will later be destroyed by a call to HWComposer::disconnectDisplay. For now, mark
1043 // it as disconnected.
1044 mDisplayData.at(*displayId).hwcDisplay->setConnected(false);
Leon Scroggins IIIe24d78f2022-09-20 16:38:19 -04001045 mComposer->onHotplugDisconnect(hwcDisplayId);
Dominik Laskowskif2ddca62022-08-17 12:08:07 -07001046 return DisplayIdentificationInfo{.id = *displayId};
Steven Thomas6e8f7062017-11-22 14:15:29 -08001047}
1048
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001049void HWComposer::loadCapabilities() {
Peiyong Line9d809e2020-04-14 13:10:48 -07001050 static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001051 auto capabilities = mComposer->getCapabilities();
1052 for (auto capability : capabilities) {
Ady Abrahamde549d42022-01-26 19:19:17 -08001053 mCapabilities.emplace(capability);
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001054 }
1055}
1056
Sally Qibb866c12022-10-17 11:31:20 -07001057void HWComposer::loadOverlayProperties() {
1058 mComposer->getOverlaySupport(&mOverlayProperties);
1059}
1060
Kriti Dang674b9372022-11-18 10:58:44 +01001061void HWComposer::loadHdrConversionCapabilities() {
1062 const auto error = mComposer->getHdrConversionCapabilities(&mHdrConversionCapabilities);
1063 if (error != hal::Error::NONE) {
1064 ALOGE("Error in fetching HDR conversion capabilities %s", to_string(error).c_str());
1065 mHdrConversionCapabilities = {};
1066 }
1067}
1068
ramindani32cf0602022-03-02 02:30:29 +00001069status_t HWComposer::setIdleTimerEnabled(PhysicalDisplayId displayId,
1070 std::chrono::milliseconds timeout) {
1071 ATRACE_CALL();
1072 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
1073 const auto error = mDisplayData[displayId].hwcDisplay->setIdleTimerEnabled(timeout);
1074 if (error == hal::Error::UNSUPPORTED) {
1075 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
1076 }
1077 if (error == hal::Error::BAD_PARAMETER) {
1078 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
1079 }
1080 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
1081 return NO_ERROR;
1082}
1083
ramindani06e518e2022-03-14 18:47:53 +00001084bool HWComposer::hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) const {
ramindani32cf0602022-03-02 02:30:29 +00001085 RETURN_IF_INVALID_DISPLAY(displayId, false);
ramindani06e518e2022-03-14 18:47:53 +00001086 return mDisplayData.at(displayId).hwcDisplay->hasDisplayIdleTimerCapability();
1087}
1088
1089Hwc2::AidlTransform HWComposer::getPhysicalDisplayOrientation(PhysicalDisplayId displayId) const {
1090 ATRACE_CALL();
1091 RETURN_IF_INVALID_DISPLAY(displayId, Hwc2::AidlTransform::NONE);
1092 Hwc2::AidlTransform outTransform;
1093 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
1094 const auto error = hwcDisplay->getPhysicalDisplayOrientation(&outTransform);
1095 RETURN_IF_HWC_ERROR(error, displayId, Hwc2::AidlTransform::NONE);
1096 return outTransform;
ramindani32cf0602022-03-02 02:30:29 +00001097}
1098
Lloyd Pique4603f3c2020-02-11 12:06:56 -08001099void HWComposer::loadLayerMetadataSupport() {
1100 mSupportedLayerGenericMetadata.clear();
1101
1102 std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo;
1103 const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo);
1104 if (error != hardware::graphics::composer::V2_4::Error::NONE) {
Ady Abraham3891cbe2021-03-29 11:29:31 -07001105 if (error != hardware::graphics::composer::V2_4::Error::UNSUPPORTED) {
1106 ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
1107 toString(error).c_str(), static_cast<int32_t>(error));
1108 }
Lloyd Pique4603f3c2020-02-11 12:06:56 -08001109 return;
1110 }
1111
1112 for (const auto& [name, mandatory] : supportedMetadataKeyInfo) {
1113 mSupportedLayerGenericMetadata.emplace(name, mandatory);
1114 }
1115}
1116
Lloyd Pique441d5042018-10-18 16:49:51 -07001117} // namespace impl
Dominik Laskowskif9750f22018-06-06 12:24:53 -07001118} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001119
1120// TODO(b/129481165): remove the #pragma below and fix conversion issues
1121#pragma clang diagnostic pop // ignored "-Wconversion"