blob: 05ef599ddae0fae8f727df68e10b02d04ba081b9 [file] [log] [blame]
Mathias Agopiana350ff92010-08-10 17:14:02 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Dan Stoza9e56aa02015-11-02 13:00:03 -080021// #define LOG_NDEBUG 0
22
23#undef LOG_TAG
24#define LOG_TAG "HWComposer"
Mathias Agopian2965b262012-04-08 15:13:32 -070025#define ATRACE_TAG ATRACE_TAG_GRAPHICS
26
Lloyd Pique66d68602019-02-13 14:23:31 -080027#include "HWComposer.h"
28
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080029#include <compositionengine/Output.h>
30#include <compositionengine/OutputLayer.h>
31#include <compositionengine/impl/OutputLayerCompositionState.h>
32#include <log/log.h>
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070033#include <ui/DebugUtils.h>
Mathias Agopian921e6ac2012-07-23 23:11:29 -070034#include <ui/GraphicBuffer.h>
Lloyd Pique37c2c9b2018-12-04 17:25:10 -080035#include <utils/Errors.h>
36#include <utils/Trace.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070037
Lloyd Pique66d68602019-02-13 14:23:31 -080038#include "../Layer.h" // needed only for debugging
Dominik Laskowski5690bde2020-04-23 19:04:22 -070039#include "../Promise.h"
Mathias Agopian33ceeb32013-04-01 16:54:58 -070040#include "../SurfaceFlinger.h"
Lloyd Pique66d68602019-02-13 14:23:31 -080041#include "ComposerHal.h"
42#include "HWC2.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070043
Dominik Laskowskic1f18f62018-06-13 15:17:55 -070044#define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
45 ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
46
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070047#define LOG_DISPLAY_ERROR(displayId, msg) \
Dominik Laskowski34157762018-10-31 13:07:19 -070048 ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg)
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070049
Dominik Laskowski34157762018-10-31 13:07:19 -070050#define LOG_HWC_ERROR(what, error, displayId) \
51 ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \
52 to_string(displayId).c_str(), to_string(error).c_str(), static_cast<int32_t>(error))
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070053
54#define RETURN_IF_INVALID_DISPLAY(displayId, ...) \
55 do { \
Dominik Laskowski075d3172018-05-24 15:50:06 -070056 if (mDisplayData.count(displayId) == 0) { \
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070057 LOG_DISPLAY_ERROR(displayId, "Invalid display"); \
58 return __VA_ARGS__; \
59 } \
60 } while (false)
61
62#define RETURN_IF_HWC_ERROR_FOR(what, error, displayId, ...) \
63 do { \
Peiyong Line9d809e2020-04-14 13:10:48 -070064 if (error != hal::Error::NONE) { \
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070065 LOG_HWC_ERROR(what, error, displayId); \
66 return __VA_ARGS__; \
67 } \
68 } while (false)
69
70#define RETURN_IF_HWC_ERROR(error, displayId, ...) \
71 RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)
72
Peiyong Line9d809e2020-04-14 13:10:48 -070073namespace hal = android::hardware::graphics::composer::hal;
74
Peiyong Linbdd08cc2019-12-17 21:35:14 -080075namespace {
76
77using android::hardware::Return;
78using android::hardware::Void;
Peiyong Line9d809e2020-04-14 13:10:48 -070079using android::HWC2::ComposerCallback;
Peiyong Linbdd08cc2019-12-17 21:35:14 -080080
Peiyong Line9d809e2020-04-14 13:10:48 -070081class ComposerCallbackBridge : public hal::IComposerCallback {
Peiyong Linbdd08cc2019-12-17 21:35:14 -080082public:
Peiyong Line9d809e2020-04-14 13:10:48 -070083 ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId,
Peiyong Linbdd08cc2019-12-17 21:35:14 -080084 bool vsyncSwitchingSupported)
85 : mCallback(callback),
86 mSequenceId(sequenceId),
87 mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
88
Peiyong Line9d809e2020-04-14 13:10:48 -070089 android::hardware::Return<void> onHotplug(hal::HWDisplayId display,
90 hal::Connection conn) override {
91 mCallback->onHotplugReceived(mSequenceId, display, conn);
Peiyong Linbdd08cc2019-12-17 21:35:14 -080092 return android::hardware::Void();
93 }
94
Peiyong Line9d809e2020-04-14 13:10:48 -070095 android::hardware::Return<void> onRefresh(hal::HWDisplayId display) override {
Peiyong Linbdd08cc2019-12-17 21:35:14 -080096 mCallback->onRefreshReceived(mSequenceId, display);
97 return android::hardware::Void();
98 }
99
Peiyong Line9d809e2020-04-14 13:10:48 -0700100 android::hardware::Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800101 if (!mVsyncSwitchingSupported) {
102 mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
103 } else {
104 ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
105 }
106 return android::hardware::Void();
107 }
108
Peiyong Line9d809e2020-04-14 13:10:48 -0700109 android::hardware::Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp,
110 hal::VsyncPeriodNanos vsyncPeriodNanos) override {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800111 if (mVsyncSwitchingSupported) {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800112 mCallback->onVsyncReceived(mSequenceId, display, timestamp,
113 std::make_optional(vsyncPeriodNanos));
114 } else {
115 ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
116 }
117 return android::hardware::Void();
118 }
119
120 android::hardware::Return<void> onVsyncPeriodTimingChanged(
Peiyong Line9d809e2020-04-14 13:10:48 -0700121 hal::HWDisplayId display,
122 const hal::VsyncPeriodChangeTimeline& updatedTimeline) override {
123 mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, updatedTimeline);
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800124 return android::hardware::Void();
125 }
126
Peiyong Line9d809e2020-04-14 13:10:48 -0700127 android::hardware::Return<void> onSeamlessPossible(hal::HWDisplayId display) override {
Ady Abrahamb0433bc2020-01-08 17:31:06 -0800128 mCallback->onSeamlessPossible(mSequenceId, display);
129 return android::hardware::Void();
130 }
131
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800132private:
Peiyong Line9d809e2020-04-14 13:10:48 -0700133 ComposerCallback* mCallback;
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800134 const int32_t mSequenceId;
135 const bool mVsyncSwitchingSupported;
136};
137
138} // namespace
139
Mathias Agopiana350ff92010-08-10 17:14:02 -0700140namespace android {
Jesse Hall5880cc52012-06-05 23:40:32 -0700141
Lloyd Pique441d5042018-10-18 16:49:51 -0700142HWComposer::~HWComposer() = default;
143
144namespace impl {
145
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800146HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) : mComposer(std::move(composer)) {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800147}
148
149HWComposer::HWComposer(const std::string& composerServiceName)
150 : mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800151}
Mathias Agopianbef42c52013-08-21 17:45:46 -0700152
Dominik Laskowskib04f98a2018-11-07 21:07:16 -0800153HWComposer::~HWComposer() {
154 mDisplayData.clear();
155}
Dan Stoza9e56aa02015-11-02 13:00:03 -0800156
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800157void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) {
158 loadCapabilities();
159 loadLayerMetadataSupport();
160
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800161 if (mRegisteredCallback) {
162 ALOGW("Callback already registered. Ignored extra registration attempt.");
163 return;
164 }
165 mRegisteredCallback = true;
166 sp<ComposerCallbackBridge> callbackBridge(
167 new ComposerCallbackBridge(callback, sequenceId,
168 mComposer->isVsyncPeriodSwitchSupported()));
169 mComposer->registerCallback(callbackBridge);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800170}
171
Peiyong Line9d809e2020-04-14 13:10:48 -0700172bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700173 DisplayIdentificationData* outData) const {
Peiyong Line9d809e2020-04-14 13:10:48 -0700174 const auto error = static_cast<hal::Error>(
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800175 mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
Peiyong Line9d809e2020-04-14 13:10:48 -0700176 if (error != hal::Error::NONE) {
177 if (error != hal::Error::UNSUPPORTED) {
Chia-I Wud0aff9d2018-06-21 13:39:09 +0800178 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
179 }
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700180 return false;
181 }
182 return true;
183}
184
Peiyong Line9d809e2020-04-14 13:10:48 -0700185bool HWComposer::hasCapability(hal::Capability capability) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800186 return mCapabilities.count(capability) > 0;
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700187}
188
Dominik Laskowski1162e472020-04-02 19:02:47 -0700189bool HWComposer::hasDisplayCapability(DisplayId displayId,
Peiyong Line9d809e2020-04-14 13:10:48 -0700190 hal::DisplayCapability capability) const {
Dominik Laskowski1162e472020-04-02 19:02:47 -0700191 RETURN_IF_INVALID_DISPLAY(displayId, false);
192 return mDisplayData.at(displayId).hwcDisplay->getCapabilities().count(capability) > 0;
Peiyong Lined531a32018-10-26 18:27:56 -0700193}
194
Peiyong Line9d809e2020-04-14 13:10:48 -0700195std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
196 hal::Connection connection) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100197 switch (connection) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700198 case hal::Connection::CONNECTED:
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100199 return onHotplugConnect(hwcDisplayId);
Peiyong Line9d809e2020-04-14 13:10:48 -0700200 case hal::Connection::DISCONNECTED:
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100201 return onHotplugDisconnect(hwcDisplayId);
Peiyong Line9d809e2020-04-14 13:10:48 -0700202 case hal::Connection::INVALID:
Dominik Laskowski075d3172018-05-24 15:50:06 -0700203 return {};
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700204 }
Andy McFaddenb0d1dd32012-09-10 14:08:09 -0700205}
206
Peiyong Line9d809e2020-04-14 13:10:48 -0700207bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700208 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
209 if (!displayId) {
210 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
Steven Thomas94e35b92017-07-26 18:48:28 -0700211 return false;
Jesse Hall1bd20e02012-08-29 10:47:52 -0700212 }
Jesse Hall1bd20e02012-08-29 10:47:52 -0700213
Dominik Laskowski075d3172018-05-24 15:50:06 -0700214 RETURN_IF_INVALID_DISPLAY(*displayId, false);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700215
Dominik Laskowski1af47932018-11-12 10:20:46 -0800216 auto& displayData = mDisplayData[*displayId];
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700217 if (displayData.isVirtual) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700218 LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display");
Steven Thomas94e35b92017-07-26 18:48:28 -0700219 return false;
Jesse Hall1bd20e02012-08-29 10:47:52 -0700220 }
221
Dan Stoza9e56aa02015-11-02 13:00:03 -0800222 {
Dominik Laskowski1af47932018-11-12 10:20:46 -0800223 std::lock_guard lock(displayData.lastHwVsyncLock);
Jesse Hall1bd20e02012-08-29 10:47:52 -0700224
Dan Stoza9e56aa02015-11-02 13:00:03 -0800225 // There have been reports of HWCs that signal several vsync events
226 // with the same timestamp when turning the display off and on. This
227 // is a bug in the HWC implementation, but filter the extra events
228 // out here so they don't cause havoc downstream.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800229 if (timestamp == displayData.lastHwVsync) {
Dominik Laskowski34157762018-10-31 13:07:19 -0700230 ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
231 to_string(*displayId).c_str(), timestamp);
Steven Thomas94e35b92017-07-26 18:48:28 -0700232 return false;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800233 }
234
Dominik Laskowski1af47932018-11-12 10:20:46 -0800235 displayData.lastHwVsync = timestamp;
Jesse Hall1c569c42013-04-05 13:44:52 -0700236 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800237
Dominik Laskowski34157762018-10-31 13:07:19 -0700238 const auto tag = "HW_VSYNC_" + to_string(*displayId);
Dominik Laskowski1af47932018-11-12 10:20:46 -0800239 ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle);
240 displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800241
Steven Thomas94e35b92017-07-26 18:48:28 -0700242 return true;
Jesse Hall1c569c42013-04-05 13:44:52 -0700243}
244
Dominik Laskowski075d3172018-05-24 15:50:06 -0700245std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
246 ui::PixelFormat* format) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800247 if (mRemainingHwcVirtualDisplays == 0) {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700248 ALOGE("%s: No remaining virtual displays", __FUNCTION__);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700249 return {};
Mathias Agopiane60b0682012-08-21 23:34:09 -0700250 }
Mathias Agopiane60b0682012-08-21 23:34:09 -0700251
Fabien Sanglardc8e387e2017-03-10 10:30:28 -0800252 if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
253 (width > SurfaceFlinger::maxVirtualDisplaySize ||
254 height > SurfaceFlinger::maxVirtualDisplaySize)) {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700255 ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width,
256 height, SurfaceFlinger::maxVirtualDisplaySize);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700257 return {};
Fabien Sanglarde29055f2017-03-08 11:36:46 -0800258 }
Peiyong Line9d809e2020-04-14 13:10:48 -0700259 hal::HWDisplayId hwcDisplayId = 0;
260 const auto error = static_cast<hal::Error>(
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800261 mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
Peiyong Line9d809e2020-04-14 13:10:48 -0700262 if (error != hal::Error::NONE) {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700263 ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700264 return {};
Mathias Agopiane60b0682012-08-21 23:34:09 -0700265 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800266
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800267 auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
Peiyong Line9d809e2020-04-14 13:10:48 -0700268 hwcDisplayId, hal::DisplayType::VIRTUAL);
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800269 display->setConnected(true);
270
Dominik Laskowski075d3172018-05-24 15:50:06 -0700271 DisplayId displayId;
272 if (mFreeVirtualDisplayIds.empty()) {
273 displayId = getVirtualDisplayId(mNextVirtualDisplayId++);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800274 } else {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700275 displayId = *mFreeVirtualDisplayIds.begin();
276 mFreeVirtualDisplayIds.erase(displayId);
Mathias Agopiane60b0682012-08-21 23:34:09 -0700277 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800278
Dominik Laskowski075d3172018-05-24 15:50:06 -0700279 auto& displayData = mDisplayData[displayId];
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800280 displayData.hwcDisplay = std::move(display);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700281 displayData.isVirtual = true;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800282
283 --mRemainingHwcVirtualDisplays;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700284 return displayId;
Mathias Agopiane60b0682012-08-21 23:34:09 -0700285}
286
Marin Shalamanova524a092020-07-27 21:39:55 +0200287void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,
288 PhysicalDisplayId displayId) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100289 if (!mInternalHwcDisplayId) {
290 mInternalHwcDisplayId = hwcDisplayId;
291 } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) {
292 mExternalHwcDisplayId = hwcDisplayId;
293 }
294
295 auto& displayData = mDisplayData[displayId];
296 auto newDisplay =
297 std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
Peiyong Line9d809e2020-04-14 13:10:48 -0700298 hal::DisplayType::PHYSICAL);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100299 newDisplay->setConnected(true);
300 displayData.hwcDisplay = std::move(newDisplay);
301 mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
302}
303
Dominik Laskowski075d3172018-05-24 15:50:06 -0700304HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700305 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
306
Steven Thomas94e35b92017-07-26 18:48:28 -0700307 HWC2::Layer* layer;
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800308 auto error = mDisplayData[displayId].hwcDisplay->createLayer(&layer);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700309 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800310 return layer;
311}
312
Dominik Laskowski075d3172018-05-24 15:50:06 -0700313void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700314 RETURN_IF_INVALID_DISPLAY(displayId);
315
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800316 auto error = mDisplayData[displayId].hwcDisplay->destroyLayer(layer);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700317 RETURN_IF_HWC_ERROR(error, displayId);
Steven Thomas94e35b92017-07-26 18:48:28 -0700318}
319
Dominik Laskowski075d3172018-05-24 15:50:06 -0700320nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const {
321 RETURN_IF_INVALID_DISPLAY(displayId, 0);
Dominik Laskowski1af47932018-11-12 10:20:46 -0800322 const auto& displayData = mDisplayData.at(displayId);
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700323 // this returns the last refresh timestamp.
324 // if the last one is not available, we estimate it based on
325 // the refresh period and whatever closest timestamp we have.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800326 std::lock_guard lock(displayData.lastHwVsyncLock);
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700327 nsecs_t now = systemTime(CLOCK_MONOTONIC);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800328 auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
329 return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700330}
331
Dominik Laskowski075d3172018-05-24 15:50:06 -0700332bool HWComposer::isConnected(DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700333 RETURN_IF_INVALID_DISPLAY(displayId, false);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700334 return mDisplayData.at(displayId).hwcDisplay->isConnected();
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700335}
336
Dominik Laskowski075d3172018-05-24 15:50:06 -0700337std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs(
338 DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700339 RETURN_IF_INVALID_DISPLAY(displayId, {});
340
Dominik Laskowski075d3172018-05-24 15:50:06 -0700341 const auto& displayData = mDisplayData.at(displayId);
342 auto configs = displayData.hwcDisplay->getConfigs();
Dan Stoza9e56aa02015-11-02 13:00:03 -0800343 if (displayData.configMap.empty()) {
344 for (size_t i = 0; i < configs.size(); ++i) {
345 displayData.configMap[i] = configs[i];
Mathias Agopianda27af92012-09-13 18:17:13 -0700346 }
347 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800348 return configs;
Mathias Agopianda27af92012-09-13 18:17:13 -0700349}
350
Dominik Laskowski075d3172018-05-24 15:50:06 -0700351std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig(
352 DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700353 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
354
Dan Stoza9e56aa02015-11-02 13:00:03 -0800355 std::shared_ptr<const HWC2::Display::Config> config;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700356 auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config);
Peiyong Line9d809e2020-04-14 13:10:48 -0700357 if (error == hal::Error::BAD_CONFIG) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700358 LOG_DISPLAY_ERROR(displayId, "No active config");
Dan Stoza9e56aa02015-11-02 13:00:03 -0800359 return nullptr;
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700360 }
361
362 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
363
364 if (!config) {
365 LOG_DISPLAY_ERROR(displayId, "Unknown config");
Dan Stoza9e56aa02015-11-02 13:00:03 -0800366 return nullptr;
367 }
368
369 return config;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700370}
371
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800372// Composer 2.4
373
Dominik Laskowski55c85402020-01-21 16:25:47 -0800374DisplayConnectionType HWComposer::getDisplayConnectionType(DisplayId displayId) const {
375 RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal);
376 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
377
378 DisplayConnectionType type;
379 const auto error = hwcDisplay->getConnectionType(&type);
380
381 const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId
382 ? DisplayConnectionType::Internal
383 : DisplayConnectionType::External;
384
385 RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
386 return type;
387}
388
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800389bool HWComposer::isVsyncPeriodSwitchSupported(DisplayId displayId) const {
Dominik Laskowski55c85402020-01-21 16:25:47 -0800390 RETURN_IF_INVALID_DISPLAY(displayId, false);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800391 return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
392}
393
394nsecs_t HWComposer::getDisplayVsyncPeriod(DisplayId displayId) const {
Dominik Laskowski55c85402020-01-21 16:25:47 -0800395 RETURN_IF_INVALID_DISPLAY(displayId, 0);
396
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800397 nsecs_t vsyncPeriodNanos;
398 auto error = mDisplayData.at(displayId).hwcDisplay->getDisplayVsyncPeriod(&vsyncPeriodNanos);
Dominik Laskowski55c85402020-01-21 16:25:47 -0800399 RETURN_IF_HWC_ERROR(error, displayId, 0);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800400 return vsyncPeriodNanos;
401}
402
Dominik Laskowski075d3172018-05-24 15:50:06 -0700403int HWComposer::getActiveConfigIndex(DisplayId displayId) const {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700404 RETURN_IF_INVALID_DISPLAY(displayId, -1);
405
Lloyd Pique3c085a02018-05-09 19:38:32 -0700406 int index;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700407 auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index);
Peiyong Line9d809e2020-04-14 13:10:48 -0700408 if (error == hal::Error::BAD_CONFIG) {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700409 LOG_DISPLAY_ERROR(displayId, "No active config");
Lloyd Pique3c085a02018-05-09 19:38:32 -0700410 return -1;
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700411 }
412
413 RETURN_IF_HWC_ERROR(error, displayId, -1);
414
415 if (index < 0) {
416 LOG_DISPLAY_ERROR(displayId, "Unknown config");
Lloyd Pique3c085a02018-05-09 19:38:32 -0700417 return -1;
418 }
419
420 return index;
421}
422
Dominik Laskowski075d3172018-05-24 15:50:06 -0700423std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700424 RETURN_IF_INVALID_DISPLAY(displayId, {});
425
Peiyong Linfd997e02018-03-28 15:29:00 -0700426 std::vector<ui::ColorMode> modes;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700427 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700428 RETURN_IF_HWC_ERROR(error, displayId, {});
Courtney Goeltzenleuchterfad9d8c2016-06-23 11:49:50 -0600429 return modes;
430}
431
Dominik Laskowski075d3172018-05-24 15:50:06 -0700432status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
433 ui::RenderIntent renderIntent) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700434 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Michael Wright28f24d02016-07-12 13:30:53 -0700435
436 auto& displayData = mDisplayData[displayId];
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700437 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700438 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
439 decodeRenderIntent(renderIntent) + ")")
440 .c_str(),
441 error, displayId, UNKNOWN_ERROR);
Michael Wright28f24d02016-07-12 13:30:53 -0700442
443 return NO_ERROR;
444}
445
Peiyong Line9d809e2020-04-14 13:10:48 -0700446void HWComposer::setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700447 RETURN_IF_INVALID_DISPLAY(displayId);
448 auto& displayData = mDisplayData[displayId];
449
450 if (displayData.isVirtual) {
451 LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
Dan Stoza9e56aa02015-11-02 13:00:03 -0800452 return;
453 }
454
Dan Stoza9e56aa02015-11-02 13:00:03 -0800455 // NOTE: we use our own internal lock here because we have to call
456 // into the HWC with the lock held, and we want to make sure
457 // that even if HWC blocks (which it shouldn't), it won't
458 // affect other threads.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800459 std::lock_guard lock(displayData.vsyncEnabledLock);
460 if (enabled == displayData.vsyncEnabled) {
461 return;
Colin Cross10fbdb62012-07-12 17:56:34 -0700462 }
Dominik Laskowski1af47932018-11-12 10:20:46 -0800463
464 ATRACE_CALL();
465 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
466 RETURN_IF_HWC_ERROR(error, displayId);
467
468 displayData.vsyncEnabled = enabled;
469
470 const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
Peiyong Line9d809e2020-04-14 13:10:48 -0700471 ATRACE_INT(tag.c_str(), enabled == hal::Vsync::ENABLE ? 1 : 0);
Colin Cross10fbdb62012-07-12 17:56:34 -0700472}
473
Dominik Laskowski075d3172018-05-24 15:50:06 -0700474status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
475 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
476 ui::Dataspace dataspace) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700477 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Jesse Hall851cfe82013-03-20 13:44:00 -0700478
Dominik Laskowski34157762018-10-31 13:07:19 -0700479 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
Dan Stoza9e56aa02015-11-02 13:00:03 -0800480 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Daniel Nicoara1f42e3a2017-04-10 13:27:32 -0400481 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700482 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
Jesse Hall851cfe82013-03-20 13:44:00 -0700483 return NO_ERROR;
484}
485
Lloyd Pique66d68602019-02-13 14:23:31 -0800486status_t HWComposer::getDeviceCompositionChanges(
487 DisplayId displayId, bool frameUsesClientComposition,
488 std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800489 ATRACE_CALL();
490
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700491 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800492
493 auto& displayData = mDisplayData[displayId];
494 auto& hwcDisplay = displayData.hwcDisplay;
495 if (!hwcDisplay->isConnected()) {
496 return NO_ERROR;
497 }
498
499 uint32_t numTypes = 0;
500 uint32_t numRequests = 0;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700501
Peiyong Line9d809e2020-04-14 13:10:48 -0700502 hal::Error error = hal::Error::NONE;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700503
Chia-I Wu41b98d42017-12-11 11:04:36 -0800504 // First try to skip validate altogether when there is no client
505 // composition. When there is client composition, since we haven't
506 // rendered to the client target yet, we should not attempt to skip
507 // validate.
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700508 displayData.validateWasSkipped = false;
Lloyd Pique66d68602019-02-13 14:23:31 -0800509 if (!frameUsesClientComposition) {
Dominik Laskowski1af47932018-11-12 10:20:46 -0800510 sp<Fence> outPresentFence;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700511 uint32_t state = UINT32_MAX;
512 error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
Peiyong Line9d809e2020-04-14 13:10:48 -0700513 if (!hasChangesError(error)) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700514 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700515 }
516 if (state == 1) { //Present Succeeded.
Steven Thomas94e35b92017-07-26 18:48:28 -0700517 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700518 error = hwcDisplay->getReleaseFences(&releaseFences);
519 displayData.releaseFences = std::move(releaseFences);
520 displayData.lastPresentFence = outPresentFence;
521 displayData.validateWasSkipped = true;
522 displayData.presentError = error;
523 return NO_ERROR;
524 }
525 // Present failed but Validate ran.
526 } else {
527 error = hwcDisplay->validate(&numTypes, &numRequests);
528 }
529 ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
Peiyong Line9d809e2020-04-14 13:10:48 -0700530 if (!hasChangesError(error)) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700531 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800532 }
533
Lloyd Pique66d68602019-02-13 14:23:31 -0800534 android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800535 changedTypes.reserve(numTypes);
536 error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700537 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800538
Peiyong Line9d809e2020-04-14 13:10:48 -0700539 auto displayRequests = static_cast<hal::DisplayRequest>(0);
Lloyd Pique66d68602019-02-13 14:23:31 -0800540 android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800541 layerRequests.reserve(numRequests);
Lloyd Pique66d68602019-02-13 14:23:31 -0800542 error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700543 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800544
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700545 DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
546 error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800547
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700548 outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
549 std::move(layerRequests),
550 std::move(clientTargetProperty)});
Dan Stoza9e56aa02015-11-02 13:00:03 -0800551 error = hwcDisplay->acceptChanges();
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700552 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800553
554 return NO_ERROR;
555}
556
Dominik Laskowski075d3172018-05-24 15:50:06 -0700557sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700558 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700559 return mDisplayData.at(displayId).lastPresentFence;
Jesse Hall851cfe82013-03-20 13:44:00 -0700560}
561
Dominik Laskowski075d3172018-05-24 15:50:06 -0700562sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700563 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Tim Murray2d3f8b82019-12-04 16:24:17 -0800564 const auto& displayFences = mDisplayData.at(displayId).releaseFences;
565 auto fence = displayFences.find(layer);
566 if (fence == displayFences.end()) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800567 ALOGV("getLayerReleaseFence: Release fence not found");
568 return Fence::NO_FENCE;
Riley Andrews03414a12014-07-01 14:22:59 -0700569 }
Tim Murray2d3f8b82019-12-04 16:24:17 -0800570 return fence->second;
Riley Andrews03414a12014-07-01 14:22:59 -0700571}
572
Dominik Laskowski075d3172018-05-24 15:50:06 -0700573status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800574 ATRACE_CALL();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700575
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700576 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Pablo Ceballosd814cf22015-09-11 14:37:39 -0700577
Dan Stoza9e56aa02015-11-02 13:00:03 -0800578 auto& displayData = mDisplayData[displayId];
579 auto& hwcDisplay = displayData.hwcDisplay;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700580
581 if (displayData.validateWasSkipped) {
Chia-I Wuae5a6b82017-10-10 09:09:22 -0700582 // explicitly flush all pending commands
Peiyong Line9d809e2020-04-14 13:10:48 -0700583 auto error = static_cast<hal::Error>(mComposer->executeCommands());
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800584 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700585 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700586 return NO_ERROR;
587 }
588
Fabien Sanglard11d0fc32016-12-01 15:43:01 -0800589 auto error = hwcDisplay->present(&displayData.lastPresentFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700590 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700591
Steven Thomas94e35b92017-07-26 18:48:28 -0700592 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800593 error = hwcDisplay->getReleaseFences(&releaseFences);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700594 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800595
596 displayData.releaseFences = std::move(releaseFences);
597
598 return NO_ERROR;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700599}
600
Peiyong Lin65248e02020-04-18 21:15:07 -0700601status_t HWComposer::setPowerMode(DisplayId displayId, hal::PowerMode mode) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700602 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
603
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700604 const auto& displayData = mDisplayData[displayId];
605 if (displayData.isVirtual) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700606 LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
607 return INVALID_OPERATION;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800608 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700609
Peiyong Line9d809e2020-04-14 13:10:48 -0700610 if (mode == hal::PowerMode::OFF) {
611 setVsyncEnabled(displayId, hal::Vsync::DISABLE);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800612 }
613
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700614 auto& hwcDisplay = displayData.hwcDisplay;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800615 switch (mode) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700616 case hal::PowerMode::OFF:
617 case hal::PowerMode::ON:
Dan Stoza9e56aa02015-11-02 13:00:03 -0800618 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
619 {
620 auto error = hwcDisplay->setPowerMode(mode);
Peiyong Line9d809e2020-04-14 13:10:48 -0700621 if (error != hal::Error::NONE) {
622 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
623 displayId);
Peiyong Lin306e4992018-05-07 16:18:22 -0700624 }
Mathias Agopianda27af92012-09-13 18:17:13 -0700625 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800626 break;
Peiyong Line9d809e2020-04-14 13:10:48 -0700627 case hal::PowerMode::DOZE:
628 case hal::PowerMode::DOZE_SUSPEND:
Dan Stoza9e56aa02015-11-02 13:00:03 -0800629 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
630 {
631 bool supportsDoze = false;
632 auto error = hwcDisplay->supportsDoze(&supportsDoze);
Peiyong Line9d809e2020-04-14 13:10:48 -0700633 if (error != hal::Error::NONE) {
Peiyong Lin306e4992018-05-07 16:18:22 -0700634 LOG_HWC_ERROR("supportsDoze", error, displayId);
635 }
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700636
Dan Stoza9e56aa02015-11-02 13:00:03 -0800637 if (!supportsDoze) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700638 mode = hal::PowerMode::ON;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800639 }
640
641 error = hwcDisplay->setPowerMode(mode);
Peiyong Line9d809e2020-04-14 13:10:48 -0700642 if (error != hal::Error::NONE) {
643 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
644 displayId);
Peiyong Lin306e4992018-05-07 16:18:22 -0700645 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800646 }
647 break;
648 default:
649 ALOGV("setPowerMode: Not calling HWC");
650 break;
Mathias Agopianda27af92012-09-13 18:17:13 -0700651 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800652
653 return NO_ERROR;
654}
655
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800656status_t HWComposer::setActiveConfigWithConstraints(
Peiyong Line9d809e2020-04-14 13:10:48 -0700657 DisplayId displayId, size_t configId, const hal::VsyncPeriodChangeConstraints& constraints,
658 hal::VsyncPeriodChangeTimeline* outTimeline) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700659 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800660
661 auto& displayData = mDisplayData[displayId];
662 if (displayData.configMap.count(configId) == 0) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700663 LOG_DISPLAY_ERROR(displayId, ("Invalid config " + std::to_string(configId)).c_str());
Dan Stoza9e56aa02015-11-02 13:00:03 -0800664 return BAD_INDEX;
665 }
666
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800667 auto error =
668 displayData.hwcDisplay->setActiveConfigWithConstraints(displayData.configMap[configId],
669 constraints, outTimeline);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700670 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800671 return NO_ERROR;
672}
673
Dominik Laskowski075d3172018-05-24 15:50:06 -0700674status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700675 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700676
677 auto& displayData = mDisplayData[displayId];
678 bool isIdentity = transform == mat4();
Peiyong Line9d809e2020-04-14 13:10:48 -0700679 auto error = displayData.hwcDisplay
680 ->setColorTransform(transform,
681 isIdentity ? hal::ColorTransform::IDENTITY
682 : hal::ColorTransform::ARBITRARY_MATRIX);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700683 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700684 return NO_ERROR;
685}
686
Dominik Laskowski075d3172018-05-24 15:50:06 -0700687void HWComposer::disconnectDisplay(DisplayId displayId) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700688 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800689 auto& displayData = mDisplayData[displayId];
690
Dan Stoza9e56aa02015-11-02 13:00:03 -0800691 // If this was a virtual display, add its slot back for reuse by future
692 // virtual displays
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700693 if (displayData.isVirtual) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700694 mFreeVirtualDisplayIds.insert(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800695 ++mRemainingHwcVirtualDisplays;
696 }
697
Dominik Laskowski7e045462018-05-30 13:02:02 -0700698 const auto hwcDisplayId = displayData.hwcDisplay->getId();
Dominik Laskowski075d3172018-05-24 15:50:06 -0700699
700 // TODO(b/74619554): Select internal/external display from remaining displays.
701 if (hwcDisplayId == mInternalHwcDisplayId) {
702 mInternalHwcDisplayId.reset();
703 } else if (hwcDisplayId == mExternalHwcDisplayId) {
704 mExternalHwcDisplayId.reset();
705 }
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800706 mPhysicalDisplayIdMap.erase(hwcDisplayId);
707 mDisplayData.erase(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800708}
709
Dominik Laskowski075d3172018-05-24 15:50:06 -0700710status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
711 const sp<GraphicBuffer>& buffer) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700712 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700713 const auto& displayData = mDisplayData[displayId];
Dan Stoza9e56aa02015-11-02 13:00:03 -0800714
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700715 if (!displayData.isVirtual) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700716 LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display");
Dan Stoza9e56aa02015-11-02 13:00:03 -0800717 return INVALID_OPERATION;
718 }
719
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700720 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700721 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800722 return NO_ERROR;
723}
724
Dominik Laskowski075d3172018-05-24 15:50:06 -0700725void HWComposer::clearReleaseFences(DisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700726 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800727 mDisplayData[displayId].releaseFences.clear();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700728}
729
Dominik Laskowski075d3172018-05-24 15:50:06 -0700730status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700731 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stozac4f471e2016-03-24 09:31:08 -0700732
733 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Peiyong Lin62665892018-04-16 11:07:44 -0700734 auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700735 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Peiyong Lin62665892018-04-16 11:07:44 -0700736 return NO_ERROR;
Dan Stozac4f471e2016-03-24 09:31:08 -0700737}
738
Dominik Laskowski075d3172018-05-24 15:50:06 -0700739int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700740 RETURN_IF_INVALID_DISPLAY(displayId, 0);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700741 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
Peiyong Lin0ac5f4e2018-04-19 22:06:34 -0700742}
743
Dominik Laskowski075d3172018-05-24 15:50:06 -0700744std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId,
745 ui::ColorMode colorMode) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700746 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700747
748 std::vector<ui::RenderIntent> renderIntents;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700749 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700750 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700751 return renderIntents;
752}
753
Dominik Laskowski075d3172018-05-24 15:50:06 -0700754mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700755 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700756
757 mat4 matrix;
758 auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
759 &matrix);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700760 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700761 return matrix;
762}
763
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700764status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId,
765 ui::PixelFormat* outFormat,
766 ui::Dataspace* outDataspace,
767 uint8_t* outComponentMask) {
768 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
769 const auto error =
770 mDisplayData[displayId]
771 .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
772 outComponentMask);
Peiyong Line9d809e2020-04-14 13:10:48 -0700773 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700774 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
775 return NO_ERROR;
776}
777
Kevin DuBois74e53772018-11-19 10:52:38 -0800778status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
779 uint8_t componentMask, uint64_t maxFrames) {
780 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
781 const auto error =
782 mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
783 componentMask,
784 maxFrames);
785
Peiyong Line9d809e2020-04-14 13:10:48 -0700786 if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
787 if (error == hal::Error::BAD_PARAMETER) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
Kevin DuBois74e53772018-11-19 10:52:38 -0800788 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
789 return NO_ERROR;
790}
791
Kevin DuBois1d4249a2018-08-29 10:45:14 -0700792status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
793 uint64_t timestamp, DisplayedFrameStats* outStats) {
794 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
795 const auto error =
796 mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
797 outStats);
798 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
799 return NO_ERROR;
800}
801
Dominik Laskowski5690bde2020-04-23 19:04:22 -0700802std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) {
803 RETURN_IF_INVALID_DISPLAY(displayId, promise::yield<status_t>(BAD_INDEX));
804 auto& display = mDisplayData[displayId].hwcDisplay;
805
806 return promise::chain(display->setDisplayBrightness(brightness))
807 .then([displayId](hal::Error error) -> status_t {
808 if (error == hal::Error::UNSUPPORTED) {
809 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
810 }
811 if (error == hal::Error::BAD_PARAMETER) {
812 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
813 }
814 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
815 return NO_ERROR;
816 });
Dan Gittik57e63c52019-01-18 16:37:54 +0000817}
818
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800819bool HWComposer::isUsingVrComposer() const {
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800820 return getComposer()->isUsingVrComposer();
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800821}
822
Galia Peycheva5492cb52019-10-30 14:13:16 +0100823status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) {
824 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
825 const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
Peiyong Line9d809e2020-04-14 13:10:48 -0700826 if (error == hal::Error::UNSUPPORTED) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100827 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
828 }
Peiyong Line9d809e2020-04-14 13:10:48 -0700829 if (error == hal::Error::BAD_PARAMETER) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100830 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
831 }
832 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
833 return NO_ERROR;
834}
835
836status_t HWComposer::getSupportedContentTypes(
Peiyong Line9d809e2020-04-14 13:10:48 -0700837 DisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100838 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
839 const auto error =
840 mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes);
841
842 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
843
844 return NO_ERROR;
845}
846
Peiyong Line9d809e2020-04-14 13:10:48 -0700847status_t HWComposer::setContentType(DisplayId displayId, hal::ContentType contentType) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100848 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
849 const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
Peiyong Line9d809e2020-04-14 13:10:48 -0700850 if (error == hal::Error::UNSUPPORTED) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100851 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
852 }
Peiyong Line9d809e2020-04-14 13:10:48 -0700853 if (error == hal::Error::BAD_PARAMETER) {
Galia Peycheva5492cb52019-10-30 14:13:16 +0100854 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
855 }
856 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
857
858 return NO_ERROR;
859}
860
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800861const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
862 return mSupportedLayerGenericMetadata;
863}
864
Yiwei Zhang5434a782018-12-05 18:06:32 -0800865void HWComposer::dump(std::string& result) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800866 result.append(mComposer->dumpDebugInfo());
Mathias Agopian83727852010-09-23 18:13:21 -0700867}
868
Marin Shalamanova524a092020-07-27 21:39:55 +0200869std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
870 hal::HWDisplayId hwcDisplayId) const {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700871 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
872 it != mPhysicalDisplayIdMap.end()) {
873 return it->second;
874 }
875 return {};
876}
877
Marin Shalamanova524a092020-07-27 21:39:55 +0200878std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
879 PhysicalDisplayId displayId) const {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700880 if (const auto it = mDisplayData.find(displayId);
881 it != mDisplayData.end() && !it->second.isVirtual) {
882 return it->second.hwcDisplay->getId();
883 }
884 return {};
885}
886
Peiyong Line9d809e2020-04-14 13:10:48 -0700887bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100888 bool hasDisplayIdentificationData) const {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700889 if (isUsingVrComposer() && mInternalHwcDisplayId) {
890 ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100891 return true;
Steven Thomas6e8f7062017-11-22 14:15:29 -0800892 }
Dominik Laskowski075d3172018-05-24 15:50:06 -0700893
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100894 if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700895 ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
896 hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100897 return true;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700898 }
899
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100900 if (!mHasMultiDisplaySupport && mInternalHwcDisplayId && mExternalHwcDisplayId) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700901 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100902 return true;
903 }
904
905 return false;
906}
907
Peiyong Line9d809e2020-04-14 13:10:48 -0700908std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
909 hal::HWDisplayId hwcDisplayId) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100910 std::optional<DisplayIdentificationInfo> info;
911 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
912 info = DisplayIdentificationInfo{.id = *displayId,
913 .name = std::string(),
914 .deviceProductInfo = std::nullopt};
Dominik Laskowski075d3172018-05-24 15:50:06 -0700915 } else {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100916 uint8_t port;
917 DisplayIdentificationData data;
918 const bool hasDisplayIdentificationData =
919 getDisplayIdentificationData(hwcDisplayId, &port, &data);
920 if (mPhysicalDisplayIdMap.empty()) {
921 mHasMultiDisplaySupport = hasDisplayIdentificationData;
922 ALOGI("Switching to %s multi-display mode",
923 mHasMultiDisplaySupport ? "generalized" : "legacy");
924 }
925
926 if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
927 return {};
928 }
929
930 info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
931 const bool isPrimary = !mInternalHwcDisplayId;
932 if (mHasMultiDisplaySupport) {
933 if (const auto info = parseDisplayIdentificationData(port, data)) {
934 return *info;
935 }
936 ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
937 } else {
938 ALOGW_IF(hasDisplayIdentificationData,
939 "Ignoring identification data for display %" PRIu64, hwcDisplayId);
Peiyong Lin65248e02020-04-18 21:15:07 -0700940 port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100941 }
942
Marin Shalamanova524a092020-07-27 21:39:55 +0200943 return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100944 .name = isPrimary ? "Internal display"
945 : "External display",
946 .deviceProductInfo = std::nullopt};
947 }();
Dominik Laskowski075d3172018-05-24 15:50:06 -0700948 }
949
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100950 if (!isConnected(info->id)) {
951 allocatePhysicalDisplay(hwcDisplayId, info->id);
952 }
953 return info;
954}
955
956std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
Peiyong Line9d809e2020-04-14 13:10:48 -0700957 hal::HWDisplayId hwcDisplayId) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100958 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
959 if (!displayId) {
960 ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
961 return {};
Dominik Laskowski075d3172018-05-24 15:50:06 -0700962 }
963
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100964 // The display will later be destroyed by a call to
965 // destroyDisplay(). For now we just mark it disconnected.
966 if (isConnected(*displayId)) {
967 mDisplayData[*displayId].hwcDisplay->setConnected(false);
968 } else {
969 ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
970 }
971 // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
972 // via SurfaceFlinger's onHotplugReceived callback handling
973 return DisplayIdentificationInfo{.id = *displayId,
974 .name = std::string(),
Marin Shalamanovf5de90d2019-10-08 10:57:25 +0200975 .deviceProductInfo = std::nullopt};
Steven Thomas6e8f7062017-11-22 14:15:29 -0800976}
977
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800978void HWComposer::loadCapabilities() {
Peiyong Line9d809e2020-04-14 13:10:48 -0700979 static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800980 auto capabilities = mComposer->getCapabilities();
981 for (auto capability : capabilities) {
Peiyong Line9d809e2020-04-14 13:10:48 -0700982 mCapabilities.emplace(static_cast<hal::Capability>(capability));
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800983 }
984}
985
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800986void HWComposer::loadLayerMetadataSupport() {
987 mSupportedLayerGenericMetadata.clear();
988
989 std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo;
990 const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo);
991 if (error != hardware::graphics::composer::V2_4::Error::NONE) {
992 ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
993 toString(error).c_str(), static_cast<int32_t>(error));
994 return;
995 }
996
997 for (const auto& [name, mandatory] : supportedMetadataKeyInfo) {
998 mSupportedLayerGenericMetadata.emplace(name, mandatory);
999 }
1000}
1001
Peiyong Linbdd08cc2019-12-17 21:35:14 -08001002uint32_t HWComposer::getMaxVirtualDisplayCount() const {
1003 return mComposer->getMaxVirtualDisplayCount();
1004}
1005
Lloyd Pique441d5042018-10-18 16:49:51 -07001006} // namespace impl
Dominik Laskowskif9750f22018-06-06 12:24:53 -07001007} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001008
1009// TODO(b/129481165): remove the #pragma below and fix conversion issues
1010#pragma clang diagnostic pop // ignored "-Wconversion"