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