blob: 560299a0f35e63736ce4d1f148770b3f412f7ed7 [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
Mathias Agopian33ceeb32013-04-01 16:54:58 -070039#include "../SurfaceFlinger.h"
Lloyd Pique66d68602019-02-13 14:23:31 -080040#include "ComposerHal.h"
41#include "HWC2.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070042
Dominik Laskowskic1f18f62018-06-13 15:17:55 -070043#define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
44 ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
45
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070046#define LOG_DISPLAY_ERROR(displayId, msg) \
Dominik Laskowski34157762018-10-31 13:07:19 -070047 ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg)
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070048
Dominik Laskowski34157762018-10-31 13:07:19 -070049#define LOG_HWC_ERROR(what, error, displayId) \
50 ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \
51 to_string(displayId).c_str(), to_string(error).c_str(), static_cast<int32_t>(error))
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070052
53#define RETURN_IF_INVALID_DISPLAY(displayId, ...) \
54 do { \
Dominik Laskowski075d3172018-05-24 15:50:06 -070055 if (mDisplayData.count(displayId) == 0) { \
Dominik Laskowskifc2c0322018-04-19 14:47:33 -070056 LOG_DISPLAY_ERROR(displayId, "Invalid display"); \
57 return __VA_ARGS__; \
58 } \
59 } while (false)
60
61#define RETURN_IF_HWC_ERROR_FOR(what, error, displayId, ...) \
62 do { \
63 if (error != HWC2::Error::None) { \
64 LOG_HWC_ERROR(what, error, displayId); \
65 return __VA_ARGS__; \
66 } \
67 } while (false)
68
69#define RETURN_IF_HWC_ERROR(error, displayId, ...) \
70 RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)
71
Peiyong Linbdd08cc2019-12-17 21:35:14 -080072namespace {
73
74using android::hardware::Return;
75using android::hardware::Void;
76
77class ComposerCallbackBridge : public android::Hwc2::IComposerCallback {
78public:
79 ComposerCallbackBridge(HWC2::ComposerCallback* callback, int32_t sequenceId,
80 bool vsyncSwitchingSupported)
81 : mCallback(callback),
82 mSequenceId(sequenceId),
83 mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
84
85 android::hardware::Return<void> onHotplug(
86 android::Hwc2::Display display,
87 android::Hwc2::IComposerCallback::Connection conn) override {
88 HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
89 mCallback->onHotplugReceived(mSequenceId, display, connection);
90 return android::hardware::Void();
91 }
92
93 android::hardware::Return<void> onRefresh(android::Hwc2::Display display) override {
94 mCallback->onRefreshReceived(mSequenceId, display);
95 return android::hardware::Void();
96 }
97
98 android::hardware::Return<void> onVsync(android::Hwc2::Display display,
99 int64_t timestamp) override {
100 if (!mVsyncSwitchingSupported) {
101 mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
102 } else {
103 ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
104 }
105 return android::hardware::Void();
106 }
107
108 android::hardware::Return<void> onVsync_2_4(
109 android::Hwc2::Display display, int64_t timestamp,
110 android::Hwc2::VsyncPeriodNanos vsyncPeriodNanos) override {
111 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(
121 android::Hwc2::Display display,
122 const android::Hwc2::VsyncPeriodChangeTimeline& updatedTimeline) override {
123 hwc_vsync_period_change_timeline_t timeline;
124 timeline.newVsyncAppliedTimeNanos = updatedTimeline.newVsyncAppliedTimeNanos;
125 timeline.refreshRequired = updatedTimeline.refreshRequired;
126 timeline.refreshTimeNanos = updatedTimeline.refreshTimeNanos;
127 mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, timeline);
128 return android::hardware::Void();
129 }
130
Ady Abrahamb0433bc2020-01-08 17:31:06 -0800131 android::hardware::Return<void> onSeamlessPossible(android::Hwc2::Display display) override {
132 mCallback->onSeamlessPossible(mSequenceId, display);
133 return android::hardware::Void();
134 }
135
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800136private:
137 HWC2::ComposerCallback* mCallback;
138 const int32_t mSequenceId;
139 const bool mVsyncSwitchingSupported;
140};
141
142} // namespace
143
Mathias Agopiana350ff92010-08-10 17:14:02 -0700144namespace android {
Jesse Hall5880cc52012-06-05 23:40:32 -0700145
Lloyd Pique441d5042018-10-18 16:49:51 -0700146HWComposer::~HWComposer() = default;
147
148namespace impl {
149
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800150HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) : mComposer(std::move(composer)) {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800151}
152
153HWComposer::HWComposer(const std::string& composerServiceName)
154 : mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800155}
Mathias Agopianbef42c52013-08-21 17:45:46 -0700156
Dominik Laskowskib04f98a2018-11-07 21:07:16 -0800157HWComposer::~HWComposer() {
158 mDisplayData.clear();
159}
Dan Stoza9e56aa02015-11-02 13:00:03 -0800160
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800161void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) {
162 loadCapabilities();
163 loadLayerMetadataSupport();
164
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800165 if (mRegisteredCallback) {
166 ALOGW("Callback already registered. Ignored extra registration attempt.");
167 return;
168 }
169 mRegisteredCallback = true;
170 sp<ComposerCallbackBridge> callbackBridge(
171 new ComposerCallbackBridge(callback, sequenceId,
172 mComposer->isVsyncPeriodSwitchSupported()));
173 mComposer->registerCallback(callbackBridge);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800174}
175
Dominik Laskowskia2edf612018-06-01 13:15:16 -0700176bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700177 DisplayIdentificationData* outData) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800178 const auto error = static_cast<HWC2::Error>(
179 mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700180 if (error != HWC2::Error::None) {
Chia-I Wud0aff9d2018-06-21 13:39:09 +0800181 if (error != HWC2::Error::Unsupported) {
182 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
183 }
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700184 return false;
185 }
186 return true;
187}
188
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800189bool HWComposer::hasCapability(HWC2::Capability capability) const {
190 return mCapabilities.count(capability) > 0;
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700191}
192
Peiyong Lined531a32018-10-26 18:27:56 -0700193bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId,
194 HWC2::DisplayCapability capability) const {
195 if (!displayId) {
Peiyong Lindf65fd22019-01-03 15:17:05 -0800196 // Checkout global capabilities for displays without a corresponding HWC display.
197 if (capability == HWC2::DisplayCapability::SkipClientColorTransform) {
198 return hasCapability(HWC2::Capability::SkipClientColorTransform);
199 }
Peiyong Lined531a32018-10-26 18:27:56 -0700200 return false;
201 }
202 RETURN_IF_INVALID_DISPLAY(*displayId, false);
203 return mDisplayData.at(*displayId).hwcDisplay->getCapabilities().count(capability) > 0;
204}
205
Dominik Laskowski075d3172018-05-24 15:50:06 -0700206std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId,
207 HWC2::Connection connection) {
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100208 switch (connection) {
209 case HWC2::Connection::Connected:
210 return onHotplugConnect(hwcDisplayId);
211 case HWC2::Connection::Disconnected:
212 return onHotplugDisconnect(hwcDisplayId);
213 case HWC2::Connection::Invalid:
Dominik Laskowski075d3172018-05-24 15:50:06 -0700214 return {};
Dominik Laskowskie9ef7c42018-03-12 19:34:30 -0700215 }
Andy McFaddenb0d1dd32012-09-10 14:08:09 -0700216}
217
Dominik Laskowski075d3172018-05-24 15:50:06 -0700218bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) {
219 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
220 if (!displayId) {
221 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
Steven Thomas94e35b92017-07-26 18:48:28 -0700222 return false;
Jesse Hall1bd20e02012-08-29 10:47:52 -0700223 }
Jesse Hall1bd20e02012-08-29 10:47:52 -0700224
Dominik Laskowski075d3172018-05-24 15:50:06 -0700225 RETURN_IF_INVALID_DISPLAY(*displayId, false);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700226
Dominik Laskowski1af47932018-11-12 10:20:46 -0800227 auto& displayData = mDisplayData[*displayId];
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700228 if (displayData.isVirtual) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700229 LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display");
Steven Thomas94e35b92017-07-26 18:48:28 -0700230 return false;
Jesse Hall1bd20e02012-08-29 10:47:52 -0700231 }
232
Dan Stoza9e56aa02015-11-02 13:00:03 -0800233 {
Dominik Laskowski1af47932018-11-12 10:20:46 -0800234 std::lock_guard lock(displayData.lastHwVsyncLock);
Jesse Hall1bd20e02012-08-29 10:47:52 -0700235
Dan Stoza9e56aa02015-11-02 13:00:03 -0800236 // There have been reports of HWCs that signal several vsync events
237 // with the same timestamp when turning the display off and on. This
238 // is a bug in the HWC implementation, but filter the extra events
239 // out here so they don't cause havoc downstream.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800240 if (timestamp == displayData.lastHwVsync) {
Dominik Laskowski34157762018-10-31 13:07:19 -0700241 ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
242 to_string(*displayId).c_str(), timestamp);
Steven Thomas94e35b92017-07-26 18:48:28 -0700243 return false;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800244 }
245
Dominik Laskowski1af47932018-11-12 10:20:46 -0800246 displayData.lastHwVsync = timestamp;
Jesse Hall1c569c42013-04-05 13:44:52 -0700247 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800248
Dominik Laskowski34157762018-10-31 13:07:19 -0700249 const auto tag = "HW_VSYNC_" + to_string(*displayId);
Dominik Laskowski1af47932018-11-12 10:20:46 -0800250 ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle);
251 displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800252
Steven Thomas94e35b92017-07-26 18:48:28 -0700253 return true;
Jesse Hall1c569c42013-04-05 13:44:52 -0700254}
255
Dominik Laskowski075d3172018-05-24 15:50:06 -0700256std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
257 ui::PixelFormat* format) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800258 if (mRemainingHwcVirtualDisplays == 0) {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700259 ALOGE("%s: No remaining virtual displays", __FUNCTION__);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700260 return {};
Mathias Agopiane60b0682012-08-21 23:34:09 -0700261 }
Mathias Agopiane60b0682012-08-21 23:34:09 -0700262
Fabien Sanglardc8e387e2017-03-10 10:30:28 -0800263 if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
264 (width > SurfaceFlinger::maxVirtualDisplaySize ||
265 height > SurfaceFlinger::maxVirtualDisplaySize)) {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700266 ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width,
267 height, SurfaceFlinger::maxVirtualDisplaySize);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700268 return {};
Fabien Sanglarde29055f2017-03-08 11:36:46 -0800269 }
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800270 hwc2_display_t hwcDisplayId = 0;
271 const auto error = static_cast<HWC2::Error>(
272 mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
Dan Stoza9e56aa02015-11-02 13:00:03 -0800273 if (error != HWC2::Error::None) {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700274 ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700275 return {};
Mathias Agopiane60b0682012-08-21 23:34:09 -0700276 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800277
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800278 auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
279 hwcDisplayId, HWC2::DisplayType::Virtual);
280 display->setConnected(true);
281
Dominik Laskowski075d3172018-05-24 15:50:06 -0700282 DisplayId displayId;
283 if (mFreeVirtualDisplayIds.empty()) {
284 displayId = getVirtualDisplayId(mNextVirtualDisplayId++);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800285 } else {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700286 displayId = *mFreeVirtualDisplayIds.begin();
287 mFreeVirtualDisplayIds.erase(displayId);
Mathias Agopiane60b0682012-08-21 23:34:09 -0700288 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800289
Dominik Laskowski075d3172018-05-24 15:50:06 -0700290 auto& displayData = mDisplayData[displayId];
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800291 displayData.hwcDisplay = std::move(display);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700292 displayData.isVirtual = true;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800293
294 --mRemainingHwcVirtualDisplays;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700295 return displayId;
Mathias Agopiane60b0682012-08-21 23:34:09 -0700296}
297
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100298void HWComposer::allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) {
299 if (!mInternalHwcDisplayId) {
300 mInternalHwcDisplayId = hwcDisplayId;
301 } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) {
302 mExternalHwcDisplayId = hwcDisplayId;
303 }
304
305 auto& displayData = mDisplayData[displayId];
306 auto newDisplay =
307 std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
308 HWC2::DisplayType::Physical);
309 newDisplay->setConnected(true);
310 displayData.hwcDisplay = std::move(newDisplay);
311 mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
312}
313
Dominik Laskowski075d3172018-05-24 15:50:06 -0700314HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700315 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
316
Steven Thomas94e35b92017-07-26 18:48:28 -0700317 HWC2::Layer* layer;
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800318 auto error = mDisplayData[displayId].hwcDisplay->createLayer(&layer);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700319 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800320 return layer;
321}
322
Dominik Laskowski075d3172018-05-24 15:50:06 -0700323void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700324 RETURN_IF_INVALID_DISPLAY(displayId);
325
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800326 auto error = mDisplayData[displayId].hwcDisplay->destroyLayer(layer);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700327 RETURN_IF_HWC_ERROR(error, displayId);
Steven Thomas94e35b92017-07-26 18:48:28 -0700328}
329
Dominik Laskowski075d3172018-05-24 15:50:06 -0700330nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const {
331 RETURN_IF_INVALID_DISPLAY(displayId, 0);
Dominik Laskowski1af47932018-11-12 10:20:46 -0800332 const auto& displayData = mDisplayData.at(displayId);
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700333 // this returns the last refresh timestamp.
334 // if the last one is not available, we estimate it based on
335 // the refresh period and whatever closest timestamp we have.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800336 std::lock_guard lock(displayData.lastHwVsyncLock);
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700337 nsecs_t now = systemTime(CLOCK_MONOTONIC);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800338 auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
339 return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700340}
341
Dominik Laskowski075d3172018-05-24 15:50:06 -0700342bool HWComposer::isConnected(DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700343 RETURN_IF_INVALID_DISPLAY(displayId, false);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700344 return mDisplayData.at(displayId).hwcDisplay->isConnected();
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700345}
346
Dominik Laskowski075d3172018-05-24 15:50:06 -0700347std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs(
348 DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700349 RETURN_IF_INVALID_DISPLAY(displayId, {});
350
Dominik Laskowski075d3172018-05-24 15:50:06 -0700351 const auto& displayData = mDisplayData.at(displayId);
352 auto configs = displayData.hwcDisplay->getConfigs();
Dan Stoza9e56aa02015-11-02 13:00:03 -0800353 if (displayData.configMap.empty()) {
354 for (size_t i = 0; i < configs.size(); ++i) {
355 displayData.configMap[i] = configs[i];
Mathias Agopianda27af92012-09-13 18:17:13 -0700356 }
357 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800358 return configs;
Mathias Agopianda27af92012-09-13 18:17:13 -0700359}
360
Dominik Laskowski075d3172018-05-24 15:50:06 -0700361std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig(
362 DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700363 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
364
Dan Stoza9e56aa02015-11-02 13:00:03 -0800365 std::shared_ptr<const HWC2::Display::Config> config;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700366 auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800367 if (error == HWC2::Error::BadConfig) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700368 LOG_DISPLAY_ERROR(displayId, "No active config");
Dan Stoza9e56aa02015-11-02 13:00:03 -0800369 return nullptr;
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700370 }
371
372 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
373
374 if (!config) {
375 LOG_DISPLAY_ERROR(displayId, "Unknown config");
Dan Stoza9e56aa02015-11-02 13:00:03 -0800376 return nullptr;
377 }
378
379 return config;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700380}
381
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800382// Composer 2.4
383
Dominik Laskowski55c85402020-01-21 16:25:47 -0800384DisplayConnectionType HWComposer::getDisplayConnectionType(DisplayId displayId) const {
385 RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal);
386 const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
387
388 DisplayConnectionType type;
389 const auto error = hwcDisplay->getConnectionType(&type);
390
391 const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId
392 ? DisplayConnectionType::Internal
393 : DisplayConnectionType::External;
394
395 RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
396 return type;
397}
398
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800399bool HWComposer::isVsyncPeriodSwitchSupported(DisplayId displayId) const {
Dominik Laskowski55c85402020-01-21 16:25:47 -0800400 RETURN_IF_INVALID_DISPLAY(displayId, false);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800401 return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
402}
403
404nsecs_t HWComposer::getDisplayVsyncPeriod(DisplayId displayId) const {
Dominik Laskowski55c85402020-01-21 16:25:47 -0800405 RETURN_IF_INVALID_DISPLAY(displayId, 0);
406
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800407 nsecs_t vsyncPeriodNanos;
408 auto error = mDisplayData.at(displayId).hwcDisplay->getDisplayVsyncPeriod(&vsyncPeriodNanos);
Dominik Laskowski55c85402020-01-21 16:25:47 -0800409 RETURN_IF_HWC_ERROR(error, displayId, 0);
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800410 return vsyncPeriodNanos;
411}
412
Dominik Laskowski075d3172018-05-24 15:50:06 -0700413int HWComposer::getActiveConfigIndex(DisplayId displayId) const {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700414 RETURN_IF_INVALID_DISPLAY(displayId, -1);
415
Lloyd Pique3c085a02018-05-09 19:38:32 -0700416 int index;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700417 auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index);
Lloyd Pique3c085a02018-05-09 19:38:32 -0700418 if (error == HWC2::Error::BadConfig) {
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700419 LOG_DISPLAY_ERROR(displayId, "No active config");
Lloyd Pique3c085a02018-05-09 19:38:32 -0700420 return -1;
Dominik Laskowskif3749f82018-06-13 15:49:25 -0700421 }
422
423 RETURN_IF_HWC_ERROR(error, displayId, -1);
424
425 if (index < 0) {
426 LOG_DISPLAY_ERROR(displayId, "Unknown config");
Lloyd Pique3c085a02018-05-09 19:38:32 -0700427 return -1;
428 }
429
430 return index;
431}
432
Dominik Laskowski075d3172018-05-24 15:50:06 -0700433std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700434 RETURN_IF_INVALID_DISPLAY(displayId, {});
435
Peiyong Linfd997e02018-03-28 15:29:00 -0700436 std::vector<ui::ColorMode> modes;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700437 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700438 RETURN_IF_HWC_ERROR(error, displayId, {});
Courtney Goeltzenleuchterfad9d8c2016-06-23 11:49:50 -0600439 return modes;
440}
441
Dominik Laskowski075d3172018-05-24 15:50:06 -0700442status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
443 ui::RenderIntent renderIntent) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700444 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Michael Wright28f24d02016-07-12 13:30:53 -0700445
446 auto& displayData = mDisplayData[displayId];
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700447 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700448 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
449 decodeRenderIntent(renderIntent) + ")")
450 .c_str(),
451 error, displayId, UNKNOWN_ERROR);
Michael Wright28f24d02016-07-12 13:30:53 -0700452
453 return NO_ERROR;
454}
455
Dominik Laskowski075d3172018-05-24 15:50:06 -0700456void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700457 RETURN_IF_INVALID_DISPLAY(displayId);
458 auto& displayData = mDisplayData[displayId];
459
460 if (displayData.isVirtual) {
461 LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
Dan Stoza9e56aa02015-11-02 13:00:03 -0800462 return;
463 }
464
Dan Stoza9e56aa02015-11-02 13:00:03 -0800465 // NOTE: we use our own internal lock here because we have to call
466 // into the HWC with the lock held, and we want to make sure
467 // that even if HWC blocks (which it shouldn't), it won't
468 // affect other threads.
Dominik Laskowski1af47932018-11-12 10:20:46 -0800469 std::lock_guard lock(displayData.vsyncEnabledLock);
470 if (enabled == displayData.vsyncEnabled) {
471 return;
Colin Cross10fbdb62012-07-12 17:56:34 -0700472 }
Dominik Laskowski1af47932018-11-12 10:20:46 -0800473
474 ATRACE_CALL();
475 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
476 RETURN_IF_HWC_ERROR(error, displayId);
477
478 displayData.vsyncEnabled = enabled;
479
480 const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
481 ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0);
Colin Cross10fbdb62012-07-12 17:56:34 -0700482}
483
Dominik Laskowski075d3172018-05-24 15:50:06 -0700484status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
485 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
486 ui::Dataspace dataspace) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700487 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Jesse Hall851cfe82013-03-20 13:44:00 -0700488
Dominik Laskowski34157762018-10-31 13:07:19 -0700489 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
Dan Stoza9e56aa02015-11-02 13:00:03 -0800490 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Daniel Nicoara1f42e3a2017-04-10 13:27:32 -0400491 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700492 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
Jesse Hall851cfe82013-03-20 13:44:00 -0700493 return NO_ERROR;
494}
495
Lloyd Pique66d68602019-02-13 14:23:31 -0800496status_t HWComposer::getDeviceCompositionChanges(
497 DisplayId displayId, bool frameUsesClientComposition,
498 std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800499 ATRACE_CALL();
500
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700501 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800502
503 auto& displayData = mDisplayData[displayId];
504 auto& hwcDisplay = displayData.hwcDisplay;
505 if (!hwcDisplay->isConnected()) {
506 return NO_ERROR;
507 }
508
509 uint32_t numTypes = 0;
510 uint32_t numRequests = 0;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700511
512 HWC2::Error error = HWC2::Error::None;
513
Chia-I Wu41b98d42017-12-11 11:04:36 -0800514 // First try to skip validate altogether when there is no client
515 // composition. When there is client composition, since we haven't
516 // rendered to the client target yet, we should not attempt to skip
517 // validate.
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700518 displayData.validateWasSkipped = false;
Lloyd Pique66d68602019-02-13 14:23:31 -0800519 if (!frameUsesClientComposition) {
Dominik Laskowski1af47932018-11-12 10:20:46 -0800520 sp<Fence> outPresentFence;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700521 uint32_t state = UINT32_MAX;
522 error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700523 if (error != HWC2::Error::HasChanges) {
524 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700525 }
526 if (state == 1) { //Present Succeeded.
Steven Thomas94e35b92017-07-26 18:48:28 -0700527 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700528 error = hwcDisplay->getReleaseFences(&releaseFences);
529 displayData.releaseFences = std::move(releaseFences);
530 displayData.lastPresentFence = outPresentFence;
531 displayData.validateWasSkipped = true;
532 displayData.presentError = error;
533 return NO_ERROR;
534 }
535 // Present failed but Validate ran.
536 } else {
537 error = hwcDisplay->validate(&numTypes, &numRequests);
538 }
539 ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700540 if (error != HWC2::Error::HasChanges) {
541 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800542 }
543
Lloyd Pique66d68602019-02-13 14:23:31 -0800544 android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800545 changedTypes.reserve(numTypes);
546 error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700547 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800548
Lloyd Pique66d68602019-02-13 14:23:31 -0800549 auto displayRequests = static_cast<HWC2::DisplayRequest>(0);
550 android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800551 layerRequests.reserve(numRequests);
Lloyd Pique66d68602019-02-13 14:23:31 -0800552 error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700553 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800554
Lloyd Pique66d68602019-02-13 14:23:31 -0800555 outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
556 std::move(layerRequests)});
Dan Stoza9e56aa02015-11-02 13:00:03 -0800557
558 error = hwcDisplay->acceptChanges();
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700559 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800560
561 return NO_ERROR;
562}
563
Dominik Laskowski075d3172018-05-24 15:50:06 -0700564sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700565 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700566 return mDisplayData.at(displayId).lastPresentFence;
Jesse Hall851cfe82013-03-20 13:44:00 -0700567}
568
Dominik Laskowski075d3172018-05-24 15:50:06 -0700569sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700570 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
Tim Murray2d3f8b82019-12-04 16:24:17 -0800571 const auto& displayFences = mDisplayData.at(displayId).releaseFences;
572 auto fence = displayFences.find(layer);
573 if (fence == displayFences.end()) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800574 ALOGV("getLayerReleaseFence: Release fence not found");
575 return Fence::NO_FENCE;
Riley Andrews03414a12014-07-01 14:22:59 -0700576 }
Tim Murray2d3f8b82019-12-04 16:24:17 -0800577 return fence->second;
Riley Andrews03414a12014-07-01 14:22:59 -0700578}
579
Dominik Laskowski075d3172018-05-24 15:50:06 -0700580status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
Dan Stoza9e56aa02015-11-02 13:00:03 -0800581 ATRACE_CALL();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700582
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700583 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Pablo Ceballosd814cf22015-09-11 14:37:39 -0700584
Dan Stoza9e56aa02015-11-02 13:00:03 -0800585 auto& displayData = mDisplayData[displayId];
586 auto& hwcDisplay = displayData.hwcDisplay;
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700587
588 if (displayData.validateWasSkipped) {
Chia-I Wuae5a6b82017-10-10 09:09:22 -0700589 // explicitly flush all pending commands
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800590 auto error = static_cast<HWC2::Error>(mComposer->executeCommands());
591 RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700592 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
Fabien Sanglard249c0ae2017-06-19 19:22:36 -0700593 return NO_ERROR;
594 }
595
Fabien Sanglard11d0fc32016-12-01 15:43:01 -0800596 auto error = hwcDisplay->present(&displayData.lastPresentFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700597 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700598
Steven Thomas94e35b92017-07-26 18:48:28 -0700599 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800600 error = hwcDisplay->getReleaseFences(&releaseFences);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700601 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800602
603 displayData.releaseFences = std::move(releaseFences);
604
605 return NO_ERROR;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700606}
607
Dominik Laskowski075d3172018-05-24 15:50:06 -0700608status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700609 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
610
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700611 const auto& displayData = mDisplayData[displayId];
612 if (displayData.isVirtual) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700613 LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
614 return INVALID_OPERATION;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800615 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700616
Dan Stoza9e56aa02015-11-02 13:00:03 -0800617 auto mode = static_cast<HWC2::PowerMode>(intMode);
618 if (mode == HWC2::PowerMode::Off) {
619 setVsyncEnabled(displayId, HWC2::Vsync::Disable);
620 }
621
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700622 auto& hwcDisplay = displayData.hwcDisplay;
Dan Stoza9e56aa02015-11-02 13:00:03 -0800623 switch (mode) {
624 case HWC2::PowerMode::Off:
625 case HWC2::PowerMode::On:
626 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
627 {
628 auto error = hwcDisplay->setPowerMode(mode);
Peiyong Lin306e4992018-05-07 16:18:22 -0700629 if (error != HWC2::Error::None) {
630 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(),
631 error, displayId);
632 }
Mathias Agopianda27af92012-09-13 18:17:13 -0700633 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800634 break;
635 case HWC2::PowerMode::Doze:
636 case HWC2::PowerMode::DozeSuspend:
637 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
638 {
639 bool supportsDoze = false;
640 auto error = hwcDisplay->supportsDoze(&supportsDoze);
Peiyong Lin306e4992018-05-07 16:18:22 -0700641 if (error != HWC2::Error::None) {
642 LOG_HWC_ERROR("supportsDoze", error, displayId);
643 }
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700644
Dan Stoza9e56aa02015-11-02 13:00:03 -0800645 if (!supportsDoze) {
646 mode = HWC2::PowerMode::On;
647 }
648
649 error = hwcDisplay->setPowerMode(mode);
Peiyong Lin306e4992018-05-07 16:18:22 -0700650 if (error != HWC2::Error::None) {
651 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(),
652 error, displayId);
653 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800654 }
655 break;
656 default:
657 ALOGV("setPowerMode: Not calling HWC");
658 break;
Mathias Agopianda27af92012-09-13 18:17:13 -0700659 }
Dan Stoza9e56aa02015-11-02 13:00:03 -0800660
661 return NO_ERROR;
662}
663
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800664status_t HWComposer::setActiveConfigWithConstraints(
665 DisplayId displayId, size_t configId, const HWC2::VsyncPeriodChangeConstraints& constraints,
666 HWC2::VsyncPeriodChangeTimeline* outTimeline) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700667 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800668
669 auto& displayData = mDisplayData[displayId];
670 if (displayData.configMap.count(configId) == 0) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700671 LOG_DISPLAY_ERROR(displayId, ("Invalid config " + std::to_string(configId)).c_str());
Dan Stoza9e56aa02015-11-02 13:00:03 -0800672 return BAD_INDEX;
673 }
674
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800675 auto error =
676 displayData.hwcDisplay->setActiveConfigWithConstraints(displayData.configMap[configId],
677 constraints, outTimeline);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700678 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800679 return NO_ERROR;
680}
681
Dominik Laskowski075d3172018-05-24 15:50:06 -0700682status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700683 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700684
685 auto& displayData = mDisplayData[displayId];
686 bool isIdentity = transform == mat4();
687 auto error = displayData.hwcDisplay->setColorTransform(transform,
688 isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY :
689 HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700690 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700691 return NO_ERROR;
692}
693
Dominik Laskowski075d3172018-05-24 15:50:06 -0700694void HWComposer::disconnectDisplay(DisplayId displayId) {
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700695 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800696 auto& displayData = mDisplayData[displayId];
697
Dan Stoza9e56aa02015-11-02 13:00:03 -0800698 // If this was a virtual display, add its slot back for reuse by future
699 // virtual displays
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700700 if (displayData.isVirtual) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700701 mFreeVirtualDisplayIds.insert(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800702 ++mRemainingHwcVirtualDisplays;
703 }
704
Dominik Laskowski7e045462018-05-30 13:02:02 -0700705 const auto hwcDisplayId = displayData.hwcDisplay->getId();
Dominik Laskowski075d3172018-05-24 15:50:06 -0700706
707 // TODO(b/74619554): Select internal/external display from remaining displays.
708 if (hwcDisplayId == mInternalHwcDisplayId) {
709 mInternalHwcDisplayId.reset();
710 } else if (hwcDisplayId == mExternalHwcDisplayId) {
711 mExternalHwcDisplayId.reset();
712 }
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800713 mPhysicalDisplayIdMap.erase(hwcDisplayId);
714 mDisplayData.erase(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800715}
716
Dominik Laskowski075d3172018-05-24 15:50:06 -0700717status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
718 const sp<GraphicBuffer>& buffer) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700719 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700720 const auto& displayData = mDisplayData[displayId];
Dan Stoza9e56aa02015-11-02 13:00:03 -0800721
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700722 if (!displayData.isVirtual) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700723 LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display");
Dan Stoza9e56aa02015-11-02 13:00:03 -0800724 return INVALID_OPERATION;
725 }
726
Dominik Laskowskic1f18f62018-06-13 15:17:55 -0700727 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700728 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800729 return NO_ERROR;
730}
731
Dominik Laskowski075d3172018-05-24 15:50:06 -0700732void HWComposer::clearReleaseFences(DisplayId displayId) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700733 RETURN_IF_INVALID_DISPLAY(displayId);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800734 mDisplayData[displayId].releaseFences.clear();
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700735}
736
Dominik Laskowski075d3172018-05-24 15:50:06 -0700737status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700738 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
Dan Stozac4f471e2016-03-24 09:31:08 -0700739
740 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
Peiyong Lin62665892018-04-16 11:07:44 -0700741 auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700742 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
Peiyong Lin62665892018-04-16 11:07:44 -0700743 return NO_ERROR;
Dan Stozac4f471e2016-03-24 09:31:08 -0700744}
745
Dominik Laskowski075d3172018-05-24 15:50:06 -0700746int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700747 RETURN_IF_INVALID_DISPLAY(displayId, 0);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700748 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
Peiyong Lin0ac5f4e2018-04-19 22:06:34 -0700749}
750
Dominik Laskowski075d3172018-05-24 15:50:06 -0700751std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId,
752 ui::ColorMode colorMode) const {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700753 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700754
755 std::vector<ui::RenderIntent> renderIntents;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700756 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700757 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700758 return renderIntents;
759}
760
Dominik Laskowski075d3172018-05-24 15:50:06 -0700761mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) {
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700762 RETURN_IF_INVALID_DISPLAY(displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700763
764 mat4 matrix;
765 auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
766 &matrix);
Dominik Laskowskifc2c0322018-04-19 14:47:33 -0700767 RETURN_IF_HWC_ERROR(error, displayId, {});
Peiyong Lin0e7a7912018-04-05 14:36:36 -0700768 return matrix;
769}
770
Kevin DuBois9c0a1762018-10-16 13:32:31 -0700771status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId,
772 ui::PixelFormat* outFormat,
773 ui::Dataspace* outDataspace,
774 uint8_t* outComponentMask) {
775 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
776 const auto error =
777 mDisplayData[displayId]
778 .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
779 outComponentMask);
780 if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
781 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
782 return NO_ERROR;
783}
784
Kevin DuBois74e53772018-11-19 10:52:38 -0800785status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
786 uint8_t componentMask, uint64_t maxFrames) {
787 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
788 const auto error =
789 mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
790 componentMask,
791 maxFrames);
792
793 if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
794 if (error == HWC2::Error::BadParameter) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
795 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
796 return NO_ERROR;
797}
798
Kevin DuBois1d4249a2018-08-29 10:45:14 -0700799status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
800 uint64_t timestamp, DisplayedFrameStats* outStats) {
801 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
802 const auto error =
803 mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
804 outStats);
805 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
806 return NO_ERROR;
807}
808
Dan Gittik57e63c52019-01-18 16:37:54 +0000809status_t HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) {
810 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
811 const auto error = mDisplayData[displayId].hwcDisplay->setDisplayBrightness(brightness);
812 if (error == HWC2::Error::Unsupported) {
813 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
814 }
815 if (error == HWC2::Error::BadParameter) {
816 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
817 }
818 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
819 return NO_ERROR;
820}
821
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800822bool HWComposer::isUsingVrComposer() const {
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800823 return getComposer()->isUsingVrComposer();
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800824}
825
Galia Peycheva5492cb52019-10-30 14:13:16 +0100826status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) {
827 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
828 const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
829 if (error == HWC2::Error::Unsupported) {
830 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
831 }
832 if (error == HWC2::Error::BadParameter) {
833 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
834 }
835 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
836 return NO_ERROR;
837}
838
839status_t HWComposer::getSupportedContentTypes(
840 DisplayId displayId, std::vector<HWC2::ContentType>* outSupportedContentTypes) {
841 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
842 const auto error =
843 mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes);
844
845 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
846
847 return NO_ERROR;
848}
849
850status_t HWComposer::setContentType(DisplayId displayId, HWC2::ContentType contentType) {
851 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
852 const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
853 if (error == HWC2::Error::Unsupported) {
854 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
855 }
856 if (error == HWC2::Error::BadParameter) {
857 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
858 }
859 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
860
861 return NO_ERROR;
862}
863
Lloyd Pique4603f3c2020-02-11 12:06:56 -0800864const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
865 return mSupportedLayerGenericMetadata;
866}
867
Yiwei Zhang5434a782018-12-05 18:06:32 -0800868void HWComposer::dump(std::string& result) const {
Peiyong Linbdd08cc2019-12-17 21:35:14 -0800869 result.append(mComposer->dumpDebugInfo());
Mathias Agopian83727852010-09-23 18:13:21 -0700870}
871
Dominik Laskowski075d3172018-05-24 15:50:06 -0700872std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const {
873 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
874 it != mPhysicalDisplayIdMap.end()) {
875 return it->second;
876 }
877 return {};
878}
879
880std::optional<hwc2_display_t> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const {
881 if (const auto it = mDisplayData.find(displayId);
882 it != mDisplayData.end() && !it->second.isVirtual) {
883 return it->second.hwcDisplay->getId();
884 }
885 return {};
886}
887
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100888bool HWComposer::shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId,
889 bool hasDisplayIdentificationData) const {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700890 if (isUsingVrComposer() && mInternalHwcDisplayId) {
891 ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100892 return true;
Steven Thomas6e8f7062017-11-22 14:15:29 -0800893 }
Dominik Laskowski075d3172018-05-24 15:50:06 -0700894
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100895 if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700896 ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
897 hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100898 return true;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700899 }
900
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100901 if (!mHasMultiDisplaySupport && mInternalHwcDisplayId && mExternalHwcDisplayId) {
Dominik Laskowski075d3172018-05-24 15:50:06 -0700902 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
Marin Shalamanovbdd59152020-02-14 15:30:06 +0100903 return true;
904 }
905
906 return false;
907}
908
909std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) {
910 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);
940 port = isPrimary ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL;
941 }
942
943 return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
944 .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(
957 hwc2_display_t hwcDisplayId) {
958 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() {
979 static_assert(sizeof(HWC2::Capability) == sizeof(int32_t), "Capability size has changed");
980 auto capabilities = mComposer->getCapabilities();
981 for (auto capability : capabilities) {
982 mCapabilities.emplace(static_cast<HWC2::Capability>(capability));
983 }
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"