summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/DisplayHardware/HWComposer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/DisplayHardware/HWComposer.cpp')
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp466
1 files changed, 227 insertions, 239 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7a2f0f34ee..7e45dabdea 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -26,9 +26,11 @@
#include "HWComposer.h"
+#include <android-base/properties.h>
#include <compositionengine/Output.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <ftl/future.h>
#include <log/log.h>
#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
@@ -36,8 +38,7 @@
#include <utils/Trace.h>
#include "../Layer.h" // needed only for debugging
-#include "../Promise.h"
-#include "../SurfaceFlinger.h"
+#include "../SurfaceFlingerProperties.h"
#include "ComposerHal.h"
#include "HWC2.h"
@@ -72,6 +73,7 @@
namespace hal = android::hardware::graphics::composer::hal;
+namespace android {
namespace {
using android::hardware::Return;
@@ -80,81 +82,74 @@ using android::HWC2::ComposerCallback;
class ComposerCallbackBridge : public hal::IComposerCallback {
public:
- ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId,
- bool vsyncSwitchingSupported)
- : mCallback(callback),
- mSequenceId(sequenceId),
- mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
+ ComposerCallbackBridge(ComposerCallback* callback, bool vsyncSwitchingSupported)
+ : mCallback(callback), mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
- android::hardware::Return<void> onHotplug(hal::HWDisplayId display,
- hal::Connection conn) override {
- mCallback->onHotplugReceived(mSequenceId, display, conn);
- return android::hardware::Void();
+ Return<void> onHotplug(hal::HWDisplayId display, hal::Connection connection) override {
+ mCallback->onComposerHalHotplug(display, connection);
+ return Void();
}
- android::hardware::Return<void> onRefresh(hal::HWDisplayId display) override {
- mCallback->onRefreshReceived(mSequenceId, display);
- return android::hardware::Void();
+ Return<void> onRefresh(hal::HWDisplayId display) override {
+ mCallback->onComposerHalRefresh(display);
+ return Void();
}
- android::hardware::Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override {
+ Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override {
if (!mVsyncSwitchingSupported) {
- mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
+ mCallback->onComposerHalVsync(display, timestamp, std::nullopt);
} else {
ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
}
- return android::hardware::Void();
+ return Void();
}
- android::hardware::Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp,
- hal::VsyncPeriodNanos vsyncPeriodNanos) override {
+ Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp,
+ hal::VsyncPeriodNanos vsyncPeriodNanos) override {
if (mVsyncSwitchingSupported) {
- mCallback->onVsyncReceived(mSequenceId, display, timestamp,
- std::make_optional(vsyncPeriodNanos));
+ mCallback->onComposerHalVsync(display, timestamp, vsyncPeriodNanos);
} else {
ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
}
- return android::hardware::Void();
+ return Void();
}
- android::hardware::Return<void> onVsyncPeriodTimingChanged(
- hal::HWDisplayId display,
- const hal::VsyncPeriodChangeTimeline& updatedTimeline) override {
- mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, updatedTimeline);
- return android::hardware::Void();
+ Return<void> onVsyncPeriodTimingChanged(
+ hal::HWDisplayId display, const hal::VsyncPeriodChangeTimeline& timeline) override {
+ mCallback->onComposerHalVsyncPeriodTimingChanged(display, timeline);
+ return Void();
}
- android::hardware::Return<void> onSeamlessPossible(hal::HWDisplayId display) override {
- mCallback->onSeamlessPossible(mSequenceId, display);
- return android::hardware::Void();
+ Return<void> onSeamlessPossible(hal::HWDisplayId display) override {
+ mCallback->onComposerHalSeamlessPossible(display);
+ return Void();
}
private:
- ComposerCallback* mCallback;
- const int32_t mSequenceId;
+ ComposerCallback* const mCallback;
const bool mVsyncSwitchingSupported;
};
} // namespace
-namespace android {
-
HWComposer::~HWComposer() = default;
namespace impl {
-HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) : mComposer(std::move(composer)) {
-}
+HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
+ : mComposer(std::move(composer)),
+ mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))),
+ mUpdateDeviceProductInfoOnHotplugReconnect(
+ sysprop::update_device_product_info_on_hotplug_reconnect(false)) {}
HWComposer::HWComposer(const std::string& composerServiceName)
- : mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {
-}
+ : HWComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {}
HWComposer::~HWComposer() {
mDisplayData.clear();
}
-void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) {
+void HWComposer::setCallback(HWC2::ComposerCallback* callback) {
loadCapabilities();
loadLayerMetadataSupport();
@@ -163,10 +158,9 @@ void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequ
return;
}
mRegisteredCallback = true;
- sp<ComposerCallbackBridge> callbackBridge(
- new ComposerCallbackBridge(callback, sequenceId,
- mComposer->isVsyncPeriodSwitchSupported()));
- mComposer->registerCallback(callbackBridge);
+
+ mComposer->registerCallback(
+ sp<ComposerCallbackBridge>::make(callback, mComposer->isVsyncPeriodSwitchSupported()));
}
bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
@@ -186,7 +180,7 @@ bool HWComposer::hasCapability(hal::Capability capability) const {
return mCapabilities.count(capability) > 0;
}
-bool HWComposer::hasDisplayCapability(DisplayId displayId,
+bool HWComposer::hasDisplayCapability(HalDisplayId displayId,
hal::DisplayCapability capability) const {
RETURN_IF_INVALID_DISPLAY(displayId, false);
return mDisplayData.at(displayId).hwcDisplay->getCapabilities().count(capability) > 0;
@@ -204,6 +198,10 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId
}
}
+bool HWComposer::updatesDeviceProductInfoOnHotplugReconnect() const {
+ return mUpdateDeviceProductInfoOnHotplugReconnect;
+}
+
bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) {
const auto displayId = toPhysicalDisplayId(hwcDisplayId);
if (!displayId) {
@@ -214,14 +212,10 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) {
RETURN_IF_INVALID_DISPLAY(*displayId, false);
auto& displayData = mDisplayData[*displayId];
- if (displayData.isVirtual) {
- LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display");
- return false;
- }
+ LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s",
+ __FUNCTION__, to_string(*displayId).c_str());
{
- std::lock_guard lock(displayData.lastHwVsyncLock);
-
// There have been reports of HWCs that signal several vsync events
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
@@ -242,49 +236,55 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) {
return true;
}
-std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
- ui::PixelFormat* format) {
- if (mRemainingHwcVirtualDisplays == 0) {
- ALOGE("%s: No remaining virtual displays", __FUNCTION__);
- return {};
+size_t HWComposer::getMaxVirtualDisplayCount() const {
+ return mComposer->getMaxVirtualDisplayCount();
+}
+
+size_t HWComposer::getMaxVirtualDisplayDimension() const {
+ return mMaxVirtualDisplayDimension;
+}
+
+bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size resolution,
+ ui::PixelFormat* format,
+ std::optional<PhysicalDisplayId> mirror) {
+ if (!resolution.isValid()) {
+ ALOGE("%s: Invalid resolution %dx%d", __func__, resolution.width, resolution.height);
+ return false;
}
- if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
- (width > SurfaceFlinger::maxVirtualDisplaySize ||
- height > SurfaceFlinger::maxVirtualDisplaySize)) {
- ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width,
- height, SurfaceFlinger::maxVirtualDisplaySize);
- return {};
+ const uint32_t width = static_cast<uint32_t>(resolution.width);
+ const uint32_t height = static_cast<uint32_t>(resolution.height);
+
+ if (mMaxVirtualDisplayDimension > 0 &&
+ (width > mMaxVirtualDisplayDimension || height > mMaxVirtualDisplayDimension)) {
+ ALOGE("%s: Resolution %ux%u exceeds maximum dimension %zu", __func__, width, height,
+ mMaxVirtualDisplayDimension);
+ return false;
}
- hal::HWDisplayId hwcDisplayId = 0;
- const auto error = static_cast<hal::Error>(
- mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
- if (error != hal::Error::NONE) {
- ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
- return {};
+
+ std::optional<hal::HWDisplayId> hwcMirrorId;
+ if (mirror) {
+ hwcMirrorId = fromPhysicalDisplayId(*mirror);
}
+ hal::HWDisplayId hwcDisplayId;
+ const auto error = static_cast<hal::Error>(
+ mComposer->createVirtualDisplay(width, height, format, hwcMirrorId, &hwcDisplayId));
+ RETURN_IF_HWC_ERROR_FOR("createVirtualDisplay", error, displayId, false);
+
auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
hwcDisplayId, hal::DisplayType::VIRTUAL);
display->setConnected(true);
-
- DisplayId displayId;
- if (mFreeVirtualDisplayIds.empty()) {
- displayId = getVirtualDisplayId(mNextVirtualDisplayId++);
- } else {
- displayId = *mFreeVirtualDisplayIds.begin();
- mFreeVirtualDisplayIds.erase(displayId);
- }
-
auto& displayData = mDisplayData[displayId];
displayData.hwcDisplay = std::move(display);
displayData.isVirtual = true;
-
- --mRemainingHwcVirtualDisplays;
- return displayId;
+ return true;
}
-void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) {
+void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,
+ PhysicalDisplayId displayId) {
+ mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
+
if (!mInternalHwcDisplayId) {
mInternalHwcDisplayId = hwcDisplayId;
} else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) {
@@ -297,129 +297,117 @@ void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayI
hal::DisplayType::PHYSICAL);
newDisplay->setConnected(true);
displayData.hwcDisplay = std::move(newDisplay);
- mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
}
-HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
- RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
+int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
+ hal::Attribute attribute) const {
+ int32_t value = 0;
+ auto error = static_cast<hal::Error>(
+ mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
- HWC2::Layer* layer;
- auto error = mDisplayData[displayId].hwcDisplay->createLayer(&layer);
- RETURN_IF_HWC_ERROR(error, displayId, nullptr);
- return layer;
+ RETURN_IF_HWC_ERROR_FOR("getDisplayAttribute", error, *toPhysicalDisplayId(hwcDisplayId), -1);
+ return value;
}
-void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) {
- RETURN_IF_INVALID_DISPLAY(displayId);
+std::shared_ptr<HWC2::Layer> HWComposer::createLayer(HalDisplayId displayId) {
+ RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
- auto error = mDisplayData[displayId].hwcDisplay->destroyLayer(layer);
- RETURN_IF_HWC_ERROR(error, displayId);
+ auto expected = mDisplayData[displayId].hwcDisplay->createLayer();
+ if (!expected.has_value()) {
+ auto error = std::move(expected).error();
+ RETURN_IF_HWC_ERROR(error, displayId, nullptr);
+ }
+ return std::move(expected).value();
}
-nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, 0);
- const auto& displayData = mDisplayData.at(displayId);
- // this returns the last refresh timestamp.
- // if the last one is not available, we estimate it based on
- // the refresh period and whatever closest timestamp we have.
- std::lock_guard lock(displayData.lastHwVsyncLock);
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
- return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
-}
+bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
+ if (mDisplayData.count(displayId)) {
+ return mDisplayData.at(displayId).hwcDisplay->isConnected();
+ }
-bool HWComposer::isConnected(DisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, false);
- return mDisplayData.at(displayId).hwcDisplay->isConnected();
+ return false;
}
-std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs(
- DisplayId displayId) const {
+std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
- const auto& displayData = mDisplayData.at(displayId);
- auto configs = displayData.hwcDisplay->getConfigs();
- if (displayData.configMap.empty()) {
- for (size_t i = 0; i < configs.size(); ++i) {
- displayData.configMap[i] = configs[i];
- }
+ const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
+ std::vector<hal::HWConfigId> configIds;
+ auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
+ RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
+
+ std::vector<HWCDisplayMode> modes;
+ modes.reserve(configIds.size());
+ for (auto configId : configIds) {
+ modes.push_back(HWCDisplayMode{
+ .hwcId = configId,
+ .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
+ .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
+ .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
+ .dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X),
+ .dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y),
+ .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
+ });
}
- return configs;
-}
-std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig(
- DisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
+ return modes;
+}
- std::shared_ptr<const HWC2::Display::Config> config;
- auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config);
- if (error == hal::Error::BAD_CONFIG) {
- LOG_DISPLAY_ERROR(displayId, "No active config");
- return nullptr;
- }
+std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
- RETURN_IF_HWC_ERROR(error, displayId, nullptr);
+ const auto hwcId = *fromPhysicalDisplayId(displayId);
+ ALOGV("[%" PRIu64 "] getActiveMode", hwcId);
+ hal::HWConfigId configId;
+ auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
- if (!config) {
- LOG_DISPLAY_ERROR(displayId, "Unknown config");
- return nullptr;
+ if (error == hal::Error::BAD_CONFIG) {
+ LOG_DISPLAY_ERROR(displayId, "No active mode");
+ return std::nullopt;
}
- return config;
+ return configId;
}
// Composer 2.4
-DisplayConnectionType HWComposer::getDisplayConnectionType(DisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal);
+ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal);
const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
- DisplayConnectionType type;
+ ui::DisplayConnectionType type;
const auto error = hwcDisplay->getConnectionType(&type);
const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId
- ? DisplayConnectionType::Internal
- : DisplayConnectionType::External;
+ ? ui::DisplayConnectionType::Internal
+ : ui::DisplayConnectionType::External;
RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
return type;
}
-bool HWComposer::isVsyncPeriodSwitchSupported(DisplayId displayId) const {
+bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, false);
return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
}
-nsecs_t HWComposer::getDisplayVsyncPeriod(DisplayId displayId) const {
+status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const {
RETURN_IF_INVALID_DISPLAY(displayId, 0);
- nsecs_t vsyncPeriodNanos;
- auto error = mDisplayData.at(displayId).hwcDisplay->getDisplayVsyncPeriod(&vsyncPeriodNanos);
- RETURN_IF_HWC_ERROR(error, displayId, 0);
- return vsyncPeriodNanos;
-}
-
-int HWComposer::getActiveConfigIndex(DisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, -1);
-
- int index;
- auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index);
- if (error == hal::Error::BAD_CONFIG) {
- LOG_DISPLAY_ERROR(displayId, "No active config");
- return -1;
- }
-
- RETURN_IF_HWC_ERROR(error, displayId, -1);
-
- if (index < 0) {
- LOG_DISPLAY_ERROR(displayId, "Unknown config");
- return -1;
+ if (!isVsyncPeriodSwitchSupported(displayId)) {
+ return INVALID_OPERATION;
}
-
- return index;
+ const auto hwcId = *fromPhysicalDisplayId(displayId);
+ Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
+ auto error =
+ static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
+ RETURN_IF_HWC_ERROR(error, displayId, 0);
+ *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
+ return NO_ERROR;
}
-std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const {
+std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
std::vector<ui::ColorMode> modes;
@@ -428,7 +416,7 @@ std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const
return modes;
}
-status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
+status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode,
ui::RenderIntent renderIntent) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -442,14 +430,12 @@ status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
return NO_ERROR;
}
-void HWComposer::setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) {
+void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) {
RETURN_IF_INVALID_DISPLAY(displayId);
auto& displayData = mDisplayData[displayId];
- if (displayData.isVirtual) {
- LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
- return;
- }
+ LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s",
+ __FUNCTION__, to_string(displayId).c_str());
// NOTE: we use our own internal lock here because we have to call
// into the HWC with the lock held, and we want to make sure
@@ -470,7 +456,7 @@ void HWComposer::setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) {
ATRACE_INT(tag.c_str(), enabled == hal::Vsync::ENABLE ? 1 : 0);
}
-status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
+status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot,
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
ui::Dataspace dataspace) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -483,7 +469,9 @@ status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
}
status_t HWComposer::getDeviceCompositionChanges(
- DisplayId displayId, bool frameUsesClientComposition,
+ HalDisplayId displayId, bool frameUsesClientComposition,
+ std::chrono::steady_clock::time_point earliestPresentTime,
+ const std::shared_ptr<FenceTime>& previousPresentFence,
std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
ATRACE_CALL();
@@ -500,12 +488,18 @@ status_t HWComposer::getDeviceCompositionChanges(
hal::Error error = hal::Error::NONE;
- // First try to skip validate altogether when there is no client
- // composition. When there is client composition, since we haven't
- // rendered to the client target yet, we should not attempt to skip
- // validate.
+ // First try to skip validate altogether. We can do that when
+ // 1. The previous frame has not been presented yet or already passed the
+ // earliest time to present. Otherwise, we may present a frame too early.
+ // 2. There is no client composition. Otherwise, we first need to render the
+ // client target buffer.
+ const bool prevFencePending =
+ previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
+ const bool canPresentEarly =
+ !prevFencePending && std::chrono::steady_clock::now() < earliestPresentTime;
+ const bool canSkipValidate = !canPresentEarly && !frameUsesClientComposition;
displayData.validateWasSkipped = false;
- if (!frameUsesClientComposition) {
+ if (canSkipValidate) {
sp<Fence> outPresentFence;
uint32_t state = UINT32_MAX;
error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
@@ -553,12 +547,12 @@ status_t HWComposer::getDeviceCompositionChanges(
return NO_ERROR;
}
-sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const {
+sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
return mDisplayData.at(displayId).lastPresentFence;
}
-sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const {
+sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
const auto& displayFences = mDisplayData.at(displayId).releaseFences;
auto fence = displayFences.find(layer);
@@ -569,7 +563,9 @@ sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* lay
return fence->second;
}
-status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
+status_t HWComposer::presentAndGetReleaseFences(
+ HalDisplayId displayId, std::chrono::steady_clock::time_point earliestPresentTime,
+ const std::shared_ptr<FenceTime>& previousPresentFence) {
ATRACE_CALL();
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -585,6 +581,13 @@ status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
return NO_ERROR;
}
+ const bool previousFramePending =
+ previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
+ if (!previousFramePending) {
+ ATRACE_NAME("wait for earliest present time");
+ std::this_thread::sleep_until(earliestPresentTime);
+ }
+
auto error = hwcDisplay->present(&displayData.lastPresentFence);
RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
@@ -597,14 +600,12 @@ status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
return NO_ERROR;
}
-status_t HWComposer::setPowerMode(DisplayId displayId, hal::PowerMode mode) {
+status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto& displayData = mDisplayData[displayId];
- if (displayData.isVirtual) {
- LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
- return INVALID_OPERATION;
- }
+ LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s",
+ __FUNCTION__, to_string(displayId).c_str());
if (mode == hal::PowerMode::OFF) {
setVsyncEnabled(displayId, hal::Vsync::DISABLE);
@@ -652,25 +653,20 @@ status_t HWComposer::setPowerMode(DisplayId displayId, hal::PowerMode mode) {
return NO_ERROR;
}
-status_t HWComposer::setActiveConfigWithConstraints(
- DisplayId displayId, size_t configId, const hal::VsyncPeriodChangeConstraints& constraints,
+status_t HWComposer::setActiveModeWithConstraints(
+ PhysicalDisplayId displayId, hal::HWConfigId hwcModeId,
+ const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
- auto& displayData = mDisplayData[displayId];
- if (displayData.configMap.count(configId) == 0) {
- LOG_DISPLAY_ERROR(displayId, ("Invalid config " + std::to_string(configId)).c_str());
- return BAD_INDEX;
- }
-
- auto error =
- displayData.hwcDisplay->setActiveConfigWithConstraints(displayData.configMap[configId],
- constraints, outTimeline);
+ auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
+ constraints,
+ outTimeline);
RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
return NO_ERROR;
}
-status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) {
+status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& displayData = mDisplayData[displayId];
@@ -683,17 +679,9 @@ status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transfor
return NO_ERROR;
}
-void HWComposer::disconnectDisplay(DisplayId displayId) {
+void HWComposer::disconnectDisplay(HalDisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId);
auto& displayData = mDisplayData[displayId];
-
- // If this was a virtual display, add its slot back for reuse by future
- // virtual displays
- if (displayData.isVirtual) {
- mFreeVirtualDisplayIds.insert(displayId);
- ++mRemainingHwcVirtualDisplays;
- }
-
const auto hwcDisplayId = displayData.hwcDisplay->getId();
// TODO(b/74619554): Select internal/external display from remaining displays.
@@ -706,27 +694,25 @@ void HWComposer::disconnectDisplay(DisplayId displayId) {
mDisplayData.erase(displayId);
}
-status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
+status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
const sp<GraphicBuffer>& buffer) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto& displayData = mDisplayData[displayId];
- if (!displayData.isVirtual) {
- LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display");
- return INVALID_OPERATION;
- }
+ LOG_FATAL_IF(!displayData.isVirtual, "%s: Invalid operation on physical display with ID %s",
+ __FUNCTION__, to_string(displayId).c_str());
auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
return NO_ERROR;
}
-void HWComposer::clearReleaseFences(DisplayId displayId) {
+void HWComposer::clearReleaseFences(HalDisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId);
mDisplayData[displayId].releaseFences.clear();
}
-status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) {
+status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
@@ -735,12 +721,12 @@ status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* ou
return NO_ERROR;
}
-int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const {
+int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, 0);
return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
}
-std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId,
+std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId,
ui::ColorMode colorMode) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
@@ -750,7 +736,7 @@ std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId,
return renderIntents;
}
-mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) {
+mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) {
RETURN_IF_INVALID_DISPLAY(displayId, {});
mat4 matrix;
@@ -760,7 +746,7 @@ mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace
return matrix;
}
-status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId,
+status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId,
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask) {
@@ -774,7 +760,7 @@ status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId,
return NO_ERROR;
}
-status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
+status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled,
uint8_t componentMask, uint64_t maxFrames) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error =
@@ -788,7 +774,7 @@ status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool
return NO_ERROR;
}
-status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
+status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames,
uint64_t timestamp, DisplayedFrameStats* outStats) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error =
@@ -798,11 +784,12 @@ status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t max
return NO_ERROR;
}
-std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) {
- RETURN_IF_INVALID_DISPLAY(displayId, promise::yield<status_t>(BAD_INDEX));
+std::future<status_t> HWComposer::setDisplayBrightness(PhysicalDisplayId displayId,
+ float brightness) {
+ RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX));
auto& display = mDisplayData[displayId].hwcDisplay;
- return promise::chain(display->setDisplayBrightness(brightness))
+ return ftl::chain(display->setDisplayBrightness(brightness))
.then([displayId](hal::Error error) -> status_t {
if (error == hal::Error::UNSUPPORTED) {
RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
@@ -815,11 +802,7 @@ std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, floa
});
}
-bool HWComposer::isUsingVrComposer() const {
- return getComposer()->isUsingVrComposer();
-}
-
-status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) {
+status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
if (error == hal::Error::UNSUPPORTED) {
@@ -833,7 +816,7 @@ status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) {
}
status_t HWComposer::getSupportedContentTypes(
- DisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) {
+ PhysicalDisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error =
mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes);
@@ -843,7 +826,7 @@ status_t HWComposer::getSupportedContentTypes(
return NO_ERROR;
}
-status_t HWComposer::setContentType(DisplayId displayId, hal::ContentType contentType) {
+status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
if (error == hal::Error::UNSUPPORTED) {
@@ -865,7 +848,8 @@ void HWComposer::dump(std::string& result) const {
result.append(mComposer->dumpDebugInfo());
}
-std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const {
+std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
+ hal::HWDisplayId hwcDisplayId) const {
if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
it != mPhysicalDisplayIdMap.end()) {
return it->second;
@@ -873,7 +857,8 @@ std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hal::HWDisplayId hwcDis
return {};
}
-std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const {
+std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
+ PhysicalDisplayId displayId) const {
if (const auto it = mDisplayData.find(displayId);
it != mDisplayData.end() && !it->second.isVirtual) {
return it->second.hwcDisplay->getId();
@@ -883,11 +868,6 @@ std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId disp
bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
bool hasDisplayIdentificationData) const {
- if (isUsingVrComposer() && mInternalHwcDisplayId) {
- ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
- return true;
- }
-
if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
hwcDisplayId);
@@ -909,6 +889,16 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
info = DisplayIdentificationInfo{.id = *displayId,
.name = std::string(),
.deviceProductInfo = std::nullopt};
+ if (mUpdateDeviceProductInfoOnHotplugReconnect) {
+ uint8_t port;
+ DisplayIdentificationData data;
+ getDisplayIdentificationData(hwcDisplayId, &port, &data);
+ if (auto newInfo = parseDisplayIdentificationData(port, data)) {
+ info->deviceProductInfo = std::move(newInfo->deviceProductInfo);
+ } else {
+ ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
+ }
+ }
} else {
uint8_t port;
DisplayIdentificationData data;
@@ -937,7 +927,7 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
}
- return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
+ return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
.name = isPrimary ? "Internal display"
: "External display",
.deviceProductInfo = std::nullopt};
@@ -986,8 +976,10 @@ void HWComposer::loadLayerMetadataSupport() {
std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo;
const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo);
if (error != hardware::graphics::composer::V2_4::Error::NONE) {
- ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
- toString(error).c_str(), static_cast<int32_t>(error));
+ if (error != hardware::graphics::composer::V2_4::Error::UNSUPPORTED) {
+ ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys",
+ toString(error).c_str(), static_cast<int32_t>(error));
+ }
return;
}
@@ -996,10 +988,6 @@ void HWComposer::loadLayerMetadataSupport() {
}
}
-uint32_t HWComposer::getMaxVirtualDisplayCount() const {
- return mComposer->getMaxVirtualDisplayCount();
-}
-
} // namespace impl
} // namespace android