diff options
Diffstat (limited to 'services')
31 files changed, 1099 insertions, 847 deletions
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 440f1e24e..641bd8d1c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -229,15 +229,14 @@ bool BufferLayer::isHdrY410() const { getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } -void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& display) { +void BufferLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform, + const Rect& viewport, int32_t supportedPerFrameMetadata) { // Apply this display's projection's viewport to the visible region // before giving it to the HWC HAL. - const ui::Transform& tr = display->getTransform(); - const auto& viewport = display->getViewport(); - Region visible = tr.transform(visibleRegion.intersect(viewport)); - const auto displayId = display->getId(); + Region visible = transform.transform(visibleRegion.intersect(viewport)); + if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + ALOGE("[%s] failed to setPerFrameData: no HWC layer found for display %" PRIu64, mName.string(), displayId); return; } @@ -290,7 +289,7 @@ void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& display) { } const HdrMetadata& metadata = getDrawingHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); + error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata, metadata); if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), to_string(error).c_str(), static_cast<int32_t>(error)); @@ -303,10 +302,10 @@ void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& display) { } getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata(); - getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); + getBE().compositionInfo.hwc.supportedPerFrameMetadata = supportedPerFrameMetadata; getBE().compositionInfo.hwc.colorTransform = getColorTransform(); - setHwcLayerBuffer(display); + setHwcLayerBuffer(displayId); } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { @@ -318,10 +317,10 @@ bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { return hasReadyFrame(); } -bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, +bool BufferLayer::onPostComposition(const std::optional<DisplayId>& displayId, + const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, const CompositorTiming& compositorTiming) { - // mFrameLatencyNeeded is true when a new frame was latched for the // composition. if (!mFrameLatencyNeeded) return false; @@ -352,11 +351,10 @@ bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFenc if (presentFence->isValid()) { mTimeStats.setPresentFence(layerID, mCurrentFrameNumber, presentFence); mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); - } else if (mFlinger->getHwComposer().isConnected(HWC_DISPLAY_PRIMARY)) { + } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. - const nsecs_t actualPresentTime = - mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY); + const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); mTimeStats.setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); mFrameTracker.setActualPresentTime(actualPresentTime); } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index d000d85a2..b3ea7e6bf 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -80,10 +80,12 @@ public: bool isHdrY410() const override; - void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override; + void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport, + int32_t supportedPerFrameMetadata) override; bool onPreComposition(nsecs_t refreshStartTime) override; - bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, + bool onPostComposition(const std::optional<DisplayId>& displayId, + const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, const CompositorTiming& compositorTiming) override; @@ -145,7 +147,7 @@ private: virtual status_t updateActiveBuffer() = 0; virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; - virtual void setHwcLayerBuffer(const sp<const DisplayDevice>& display) = 0; + virtual void setHwcLayerBuffer(DisplayId displayId) = 0; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index c130bc510..e10548f06 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -325,8 +325,7 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) { - const auto displayId = display->getId(); +void BufferQueueLayer::setHwcLayerBuffer(DisplayId displayId) { auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index c9ebe042b..74dd21e0d 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -94,8 +94,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override; - // ----------------------------------------------------------------------- + void setHwcLayerBuffer(DisplayId displayId) override; // ----------------------------------------------------------------------- // Interface implementation for BufferLayerConsumer::ContentsChangedListener diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 73098bf2a..8d5984157 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -497,8 +497,7 @@ status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { return NO_ERROR; } -void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) { - const auto displayId = display->getId(); +void BufferStateLayer::setHwcLayerBuffer(DisplayId displayId) { auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 0c6eaf5a3..381cd28f4 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -121,8 +121,8 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override; - // ----------------------------------------------------------------------- + void setHwcLayerBuffer(DisplayId displayId) override; + private: void onFirstRef() override; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 263f87282..ad716efa3 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -57,13 +57,12 @@ bool ColorLayer::isVisible() const { return !isHiddenByPolicy() && getAlpha() > 0.0f; } -void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& display) { - const ui::Transform& tr = display->getTransform(); - const auto& viewport = display->getViewport(); - Region visible = tr.transform(visibleRegion.intersect(viewport)); - const auto displayId = display->getId(); +void ColorLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform, + const Rect& viewport, int32_t /* supportedPerFrameMetadata */) { + Region visible = transform.transform(visibleRegion.intersect(viewport)); + if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + ALOGE("[%s] failed to setPerFrameData: no HWC layer found for display %" PRIu64, mName.string(), displayId); return; } diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 2febe9a5b..d1b1697af 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -33,7 +33,8 @@ public: bool useIdentityTransform); bool isVisible() const override; - void setPerFrameData(const sp<const DisplayDevice>& display) override; + void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport, + int32_t supportedPerFrameMetadata) override; bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; } diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 44e843e24..ca49f6c7a 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -32,6 +32,6 @@ bool ContainerLayer::isVisible() const { return !isHiddenByPolicy(); } -void ContainerLayer::setPerFrameData(const sp<const DisplayDevice>&) {} +void ContainerLayer::setPerFrameData(DisplayId, const ui::Transform&, const Rect&, int32_t) {} } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 316db83ab..413844b6f 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -33,7 +33,8 @@ public: bool useIdentityTransform) override; bool isVisible() const override; - void setPerFrameData(const sp<const DisplayDevice>& display) override; + void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport, + int32_t supportedPerFrameMetadata) override; bool isCreatedFromMainThread() const override { return true; } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 91b18c9fd..7c5c1bc8c 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -212,15 +212,14 @@ RenderIntent getHwcRenderIntent(const std::vector<RenderIntent>& hwcIntents, Ren DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& displayToken, - DisplayDevice::DisplayType type, int32_t id) - : flinger(flinger), displayToken(displayToken), type(type), id(id) {} + const std::optional<DisplayId>& displayId) + : flinger(flinger), displayToken(displayToken), displayId(displayId) {} DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) : lastCompositionHadVisibleLayers(false), mFlinger(args.flinger), - mType(args.type), - mId(args.id), mDisplayToken(args.displayToken), + mId(args.displayId), mNativeWindow(args.nativeWindow), mDisplaySurface(args.displaySurface), mSurface{std::move(args.renderSurface)}, @@ -228,6 +227,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) mDisplayHeight(args.displayHeight), mDisplayInstallOrientation(args.displayInstallOrientation), mPageFlipCount(0), + mIsVirtual(args.isVirtual), mIsSecure(args.isSecure), mLayerStack(NO_LAYER_STACK), mOrientation(), @@ -240,7 +240,8 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) mHasHdr10(false), mHasHLG(false), mHasDolbyVision(false), - mSupportedPerFrameMetadata(args.supportedPerFrameMetadata) { + mSupportedPerFrameMetadata(args.supportedPerFrameMetadata), + mIsPrimary(args.isPrimary) { populateColorModes(args.hwcColorModes); ALOGE_IF(!mNativeWindow, "No native window was set for display"); @@ -293,16 +294,12 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) DisplayDevice::~DisplayDevice() = default; void DisplayDevice::disconnect(HWComposer& hwc) { - if (mId >= 0) { - hwc.disconnectDisplay(mId); - mId = -1; + if (mId) { + hwc.disconnectDisplay(*mId); + mId.reset(); } } -bool DisplayDevice::isValid() const { - return mFlinger != nullptr; -} - int DisplayDevice::getWidth() const { return mDisplayWidth; } @@ -334,9 +331,11 @@ status_t DisplayDevice::beginFrame(bool mustRecompose) const { status_t DisplayDevice::prepareFrame(HWComposer& hwc, std::vector<CompositionInfo>& compositionData) { - status_t error = hwc.prepare(*this, compositionData); - if (error != NO_ERROR) { - return error; + if (mId) { + status_t error = hwc.prepare(*mId, compositionData); + if (error != NO_ERROR) { + return error; + } } DisplaySurface::CompositionType compositionType; @@ -600,7 +599,7 @@ void DisplayDevice::setProjection(int orientation, // need to take care of primary display rotation for mGlobalTransform // for case if the panel is not installed aligned with device orientation - if (mType == DisplayType::DISPLAY_PRIMARY) { + if (isPrimary()) { DisplayDevice::orientationToTransfrom( (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1), w, h, &R); @@ -648,7 +647,7 @@ uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() { } std::string DisplayDevice::getDebugName() const { - const auto id = mId >= 0 ? base::StringPrintf("%d, ", mId) : std::string(); + const auto id = mId ? base::StringPrintf("%" PRIu64 ", ", *mId) : std::string(); return base::StringPrintf("DisplayDevice{%s%s%s\"%s\"}", id.c_str(), isPrimary() ? "primary, " : "", isVirtual() ? "virtual, " : "", mDisplayName.c_str()); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 152d0eca5..9ec7666ea 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -20,6 +20,7 @@ #include <stdlib.h> #include <memory> +#include <optional> #include <string> #include <unordered_map> @@ -37,6 +38,7 @@ #include <utils/String8.h> #include <utils/Timers.h> +#include "DisplayHardware/DisplayIdentification.h" #include "RenderArea.h" struct ANativeWindow; @@ -66,25 +68,15 @@ public: Region undefinedRegion; bool lastCompositionHadVisibleLayers; - enum DisplayType { - DISPLAY_ID_INVALID = -1, - DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY, - DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL, - DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL, - NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES, - }; - enum { NO_LAYER_STACK = 0xFFFFFFFF, }; explicit DisplayDevice(DisplayDeviceCreationArgs&& args); - ~DisplayDevice(); - // whether this is a valid object. An invalid DisplayDevice is returned - // when an non existing id is requested - bool isValid() const; + bool isVirtual() const { return mIsVirtual; } + bool isPrimary() const { return mIsPrimary; } // isSecure indicates whether this display can be trusted to display // secure surfaces. @@ -118,11 +110,9 @@ public: bool needsFiltering() const { return mNeedsFiltering; } uint32_t getLayerStack() const { return mLayerStack; } - int32_t getDisplayType() const { return mType; } - bool isPrimary() const { return mType == DISPLAY_PRIMARY; } - bool isVirtual() const { return mType == DISPLAY_VIRTUAL; } - int32_t getId() const { return mId; } - const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } + + const std::optional<DisplayId>& getId() const { return mId; } + const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } int32_t getSupportedPerFrameMetadata() const { return mSupportedPerFrameMetadata; } @@ -207,13 +197,10 @@ public: void dump(String8& result) const; private: - /* - * Constants, set during initialization - */ - sp<SurfaceFlinger> mFlinger; - DisplayType mType; - int32_t mId; - wp<IBinder> mDisplayToken; + const sp<SurfaceFlinger> mFlinger; + const wp<IBinder> mDisplayToken; + + std::optional<DisplayId> mId; // ANativeWindow this display is rendering into sp<ANativeWindow> mNativeWindow; @@ -225,7 +212,9 @@ private: const int mDisplayInstallOrientation; mutable uint32_t mPageFlipCount; std::string mDisplayName; - bool mIsSecure; + + const bool mIsVirtual; + const bool mIsSecure; /* * Can only accessed from the main thread, these members @@ -299,13 +288,16 @@ private: const ui::ColorMode mode, const ui::RenderIntent intent); std::unordered_map<ColorModeKey, ColorModeValue> mColorModes; + + // TODO(b/74619554): Remove special cases for primary display. + const bool mIsPrimary; }; struct DisplayDeviceState { - bool isVirtual() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; } + bool isVirtual() const { return !displayId.has_value(); } int32_t sequenceId = sNextSequenceId++; - DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_ID_INVALID; + std::optional<DisplayId> displayId; sp<IGraphicBufferProducer> surface; uint32_t layerStack = DisplayDevice::NO_LAYER_STACK; Rect viewport; @@ -324,13 +316,13 @@ struct DisplayDeviceCreationArgs { // We use a constructor to ensure some of the values are set, without // assuming a default value. DisplayDeviceCreationArgs(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& displayToken, - DisplayDevice::DisplayType type, int32_t id); + const std::optional<DisplayId>& displayId); const sp<SurfaceFlinger> flinger; const wp<IBinder> displayToken; - const DisplayDevice::DisplayType type; - const int32_t id; + const std::optional<DisplayId> displayId; + bool isVirtual{false}; bool isSecure{false}; sp<ANativeWindow> nativeWindow; sp<DisplaySurface> displaySurface; @@ -343,6 +335,7 @@ struct DisplayDeviceCreationArgs { int32_t supportedPerFrameMetadata{0}; std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hwcColorModes; int initialPowerMode{HWC_POWER_MODE_NORMAL}; + bool isPrimary{false}; }; class DisplayRenderArea : public RenderArea { diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp index dcc413863..ec240f300 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp @@ -33,6 +33,9 @@ using byte_view = std::basic_string_view<uint8_t>; constexpr size_t kEdidHeaderLength = 5; +constexpr uint16_t kFallbackEdidManufacturerId = 0; +constexpr uint16_t kVirtualEdidManufacturerId = 0xffffu; + std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) { if (view.size() < kEdidHeaderLength || view[0] || view[1] || view[2] || view[4]) { return {}; @@ -165,7 +168,8 @@ std::optional<PnpId> getPnpId(uint16_t manufacturerId) { return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt; } -std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentificationData& data) { +std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData( + uint8_t port, const DisplayIdentificationData& data) { if (!isEdid(data)) { ALOGE("Display identification data has unknown format."); return {}; @@ -179,7 +183,16 @@ std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentifica // Hash display name instead of using product code or serial number, since the latter have been // observed to change on some displays with multiple inputs. const auto hash = static_cast<uint32_t>(std::hash<std::string_view>()(edid->displayName)); - return getEdidDisplayId(port, edid->manufacturerId, hash); + return DisplayIdentificationInfo{getEdidDisplayId(port, edid->manufacturerId, hash), + std::string(edid->displayName)}; +} + +DisplayId getFallbackDisplayId(uint8_t port) { + return getEdidDisplayId(port, kFallbackEdidManufacturerId, 0); +} + +DisplayId getVirtualDisplayId(uint32_t id) { + return getEdidDisplayId(0, kVirtualEdidManufacturerId, id); } } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h index 379f2d3be..1f2e789d1 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h @@ -19,6 +19,7 @@ #include <array> #include <cstdint> #include <optional> +#include <string> #include <string_view> #include <vector> @@ -27,6 +28,11 @@ namespace android { using DisplayId = uint64_t; using DisplayIdentificationData = std::vector<uint8_t>; +struct DisplayIdentificationInfo { + DisplayId id; + std::string name; +}; + // NUL-terminated plug and play ID. using PnpId = std::array<char, 4>; @@ -40,6 +46,10 @@ bool isEdid(const DisplayIdentificationData&); std::optional<Edid> parseEdid(const DisplayIdentificationData&); std::optional<PnpId> getPnpId(uint16_t manufacturerId); -std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentificationData&); +std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData( + uint8_t port, const DisplayIdentificationData&); + +DisplayId getFallbackDisplayId(uint8_t port); +DisplayId getVirtualDisplayId(uint32_t id); } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index e6d783434..f3f8d9d85 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -52,26 +52,25 @@ using ui::Dataspace; * */ -FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, - const sp<IGraphicBufferConsumer>& consumer) : - ConsumerBase(consumer), - mDisplayType(disp), - mCurrentBufferSlot(-1), - mCurrentBuffer(), - mCurrentFence(Fence::NO_FENCE), - mHwc(hwc), - mHasPendingRelease(false), - mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), - mPreviousBuffer() -{ - ALOGV("Creating for display %d", disp); +FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId, + const sp<IGraphicBufferConsumer>& consumer) + : ConsumerBase(consumer), + mDisplayId(displayId), + mCurrentBufferSlot(-1), + mCurrentBuffer(), + mCurrentFence(Fence::NO_FENCE), + mHwc(hwc), + mHasPendingRelease(false), + mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), + mPreviousBuffer() { + ALOGV("Creating for display %" PRIu64, displayId); mName = "FramebufferSurface"; mConsumer->setConsumerName(mName); mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER); - const auto& activeConfig = mHwc.getActiveConfig(disp); + const auto& activeConfig = mHwc.getActiveConfig(displayId); mConsumer->setDefaultBufferSize(activeConfig->getWidth(), activeConfig->getHeight()); mConsumer->setMaxAcquiredBufferCount( @@ -142,8 +141,7 @@ status_t FramebufferSurface::nextBuffer(uint32_t& outSlot, mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer); outDataspace = static_cast<Dataspace>(item.mDataSpace); - status_t result = - mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace); + status_t result = mHwc.setClientTarget(mDisplayId, outSlot, outFence, outBuffer, outDataspace); if (result != NO_ERROR) { ALOGE("error posting framebuffer: %d", result); return result; @@ -161,7 +159,7 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) { void FramebufferSurface::onFrameCommitted() { if (mHasPendingRelease) { - sp<Fence> fence = mHwc.getPresentFence(mDisplayType); + sp<Fence> fence = mHwc.getPresentFence(mDisplayId); if (fence->isValid()) { status_t result = addReleaseFence(mPreviousBufferSlot, mPreviousBuffer, fence); diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 0fd8e9eaa..2431dfd7c 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -17,6 +17,7 @@ #ifndef ANDROID_SF_FRAMEBUFFER_SURFACE_H #define ANDROID_SF_FRAMEBUFFER_SURFACE_H +#include "DisplayIdentification.h" #include "DisplaySurface.h" #include "HWComposerBufferCache.h" @@ -38,7 +39,8 @@ class HWComposer; class FramebufferSurface : public ConsumerBase, public DisplaySurface { public: - FramebufferSurface(HWComposer& hwc, int disp, const sp<IGraphicBufferConsumer>& consumer); + FramebufferSurface(HWComposer& hwc, DisplayId displayId, + const sp<IGraphicBufferConsumer>& consumer); virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); @@ -63,8 +65,7 @@ private: status_t nextBuffer(uint32_t& outSlot, sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence, ui::Dataspace& outDataspace); - // mDisplayType must match one of the HWC display types - int mDisplayType; + const DisplayId mDisplayId; // mCurrentBufferIndex is the slot index of the current buffer or // INVALID_BUFFER_SLOT to indicate that either there is no current buffer diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index b1daf12c6..4c472b80b 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -58,15 +58,15 @@ ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg) #define LOG_DISPLAY_ERROR(displayId, msg) \ - ALOGE("%s failed for display %d: %s", __FUNCTION__, displayId, msg) + ALOGE("%s failed for display %" PRIu64 ": %s", __FUNCTION__, displayId, msg) -#define LOG_HWC_ERROR(what, error, displayId) \ - ALOGE("%s: %s failed for display %d: %s (%d)", __FUNCTION__, what, displayId, \ +#define LOG_HWC_ERROR(what, error, displayId) \ + ALOGE("%s: %s failed for display %" PRIu64 ": %s (%d)", __FUNCTION__, what, displayId, \ to_string(error).c_str(), static_cast<int32_t>(error)) #define RETURN_IF_INVALID_DISPLAY(displayId, ...) \ do { \ - if (!isValidDisplay(displayId)) { \ + if (mDisplayData.count(displayId) == 0) { \ LOG_DISPLAY_ERROR(displayId, "Invalid display"); \ return __VA_ARGS__; \ } \ @@ -118,11 +118,6 @@ bool HWComposer::hasCapability(HWC2::Capability capability) const return mHwcDevice->getCapabilities().count(capability) > 0; } -bool HWComposer::isValidDisplay(int32_t displayId) const { - return static_cast<size_t>(displayId) < mDisplayData.size() && - mDisplayData[displayId].hwcDisplay; -} - void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { bool valid = true; switch (from) { @@ -148,52 +143,50 @@ void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { } } -std::optional<DisplayId> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType, - HWC2::Connection connection) { - if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) { - ALOGE("Invalid display type of %d", displayType); - return {}; - } - - ALOGV("hotplug: %" PRIu64 ", %s %s", hwcDisplayId, - displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external", - to_string(connection).c_str()); - mHwcDevice->onHotplug(hwcDisplayId, connection); - - std::optional<DisplayId> displayId; +std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, + HWC2::Connection connection) { + std::optional<DisplayIdentificationInfo> info; - if (connection == HWC2::Connection::Connected) { - uint8_t port; - DisplayIdentificationData data; - if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) { - displayId = generateDisplayId(port, data); - ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId); + if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) { + info = DisplayIdentificationInfo{*displayId, std::string()}; + } else { + if (connection == HWC2::Connection::Disconnected) { + ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId); + return {}; } + + info = onHotplugConnect(hwcDisplayId); + if (!info) return {}; } + ALOGV("%s: %s %s display %" PRIu64 " with HWC ID %" PRIu64, __FUNCTION__, + to_string(connection).c_str(), + hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", info->id, hwcDisplayId); + + mHwcDevice->onHotplug(hwcDisplayId, connection); + // Disconnect is handled through HWComposer::disconnectDisplay via // SurfaceFlinger's onHotplugReceived callback handling if (connection == HWC2::Connection::Connected) { - mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId); - mHwcDisplaySlots[hwcDisplayId] = displayType; + mDisplayData[info->id].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId); + mPhysicalDisplayIdMap[hwcDisplayId] = info->id; } - return displayId; + return info; } -bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplayId) { - const auto it = mHwcDisplaySlots.find(hwcDisplayId); - if (it == mHwcDisplaySlots.end()) { - LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid display"); +bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) { + const auto displayId = toPhysicalDisplayId(hwcDisplayId); + if (!displayId) { + LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display"); return false; } - const int32_t displayId = it->second; - RETURN_IF_INVALID_DISPLAY(displayId, false); + RETURN_IF_INVALID_DISPLAY(*displayId, false); - const auto& displayData = mDisplayData[displayId]; + const auto& displayData = mDisplayData[*displayId]; if (displayData.isVirtual) { - LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); + LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display"); return false; } @@ -204,31 +197,26 @@ bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t // with the same timestamp when turning the display off and on. This // is a bug in the HWC implementation, but filter the extra events // out here so they don't cause havoc downstream. - if (timestamp == mLastHwVSync[displayId]) { - ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")", - timestamp); + if (timestamp == mLastHwVSync[*displayId]) { + ALOGW("Ignoring duplicate VSYNC event from HWC for display %" PRIu64 " (t=%" PRId64 ")", + *displayId, timestamp); return false; } - mLastHwVSync[displayId] = timestamp; - } - - if (outDisplayId) { - *outDisplayId = displayId; + mLastHwVSync[*displayId] = timestamp; } - char tag[16]; - snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", displayId); - ATRACE_INT(tag, ++mVSyncCounts[displayId] & 1); + const auto tag = "HW_VSYNC_" + std::to_string(*displayId); + ATRACE_INT(tag.c_str(), ++mVSyncCounts[*displayId] & 1); return true; } -status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, - ui::PixelFormat* format, int32_t *outId) { +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 NO_MEMORY; + return {}; } if (SurfaceFlinger::maxVirtualDisplaySize != 0 && @@ -236,41 +224,33 @@ status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, height > SurfaceFlinger::maxVirtualDisplaySize)) { ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width, height, SurfaceFlinger::maxVirtualDisplaySize); - return INVALID_OPERATION; + return {}; } - HWC2::Display* display; auto error = mHwcDevice->createVirtualDisplay(width, height, format, &display); if (error != HWC2::Error::None) { ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__); - return NO_MEMORY; + return {}; } - size_t displaySlot = 0; - if (!mFreeDisplaySlots.empty()) { - displaySlot = *mFreeDisplaySlots.begin(); - mFreeDisplaySlots.erase(displaySlot); - } else if (mDisplayData.size() < INT32_MAX) { - // Don't bother allocating a slot larger than we can return - displaySlot = mDisplayData.size(); - mDisplayData.resize(displaySlot + 1); + DisplayId displayId; + if (mFreeVirtualDisplayIds.empty()) { + displayId = getVirtualDisplayId(mNextVirtualDisplayId++); } else { - ALOGE("%s: Unable to allocate a display slot", __FUNCTION__); - return NO_MEMORY; + displayId = *mFreeVirtualDisplayIds.begin(); + mFreeVirtualDisplayIds.erase(displayId); } - auto& displayData = mDisplayData[displaySlot]; + auto& displayData = mDisplayData[displayId]; displayData.hwcDisplay = display; displayData.isVirtual = true; --mRemainingHwcVirtualDisplays; - *outId = static_cast<int32_t>(displaySlot); - - return NO_ERROR; + return displayId; } -HWC2::Layer* HWComposer::createLayer(int32_t displayId) { +HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId, nullptr); auto display = mDisplayData[displayId].hwcDisplay; @@ -280,7 +260,7 @@ HWC2::Layer* HWComposer::createLayer(int32_t displayId) { return layer; } -void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) { +void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) { RETURN_IF_INVALID_DISPLAY(displayId); auto display = mDisplayData[displayId].hwcDisplay; @@ -288,7 +268,8 @@ void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) { RETURN_IF_HWC_ERROR(error, displayId); } -nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const { +nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, 0); // 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. @@ -298,17 +279,17 @@ nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const { return now - ((now - mLastHwVSync[displayId]) % vsyncPeriod); } -bool HWComposer::isConnected(int32_t displayId) const { +bool HWComposer::isConnected(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, false); - return mDisplayData[displayId].hwcDisplay->isConnected(); + return mDisplayData.at(displayId).hwcDisplay->isConnected(); } -std::vector<std::shared_ptr<const HWC2::Display::Config>> - HWComposer::getConfigs(int32_t displayId) const { +std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs( + DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); - auto& displayData = mDisplayData[displayId]; - auto configs = mDisplayData[displayId].hwcDisplay->getConfigs(); + 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]; @@ -317,12 +298,12 @@ std::vector<std::shared_ptr<const HWC2::Display::Config>> return configs; } -std::shared_ptr<const HWC2::Display::Config> - HWComposer::getActiveConfig(int32_t displayId) const { +std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig( + DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, nullptr); std::shared_ptr<const HWC2::Display::Config> config; - auto error = mDisplayData[displayId].hwcDisplay->getActiveConfig(&config); + auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config); if (error == HWC2::Error::BadConfig) { LOG_DISPLAY_ERROR(displayId, "No active config"); return nullptr; @@ -338,11 +319,11 @@ std::shared_ptr<const HWC2::Display::Config> return config; } -int HWComposer::getActiveConfigIndex(int32_t displayId) const { +int HWComposer::getActiveConfigIndex(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, -1); int index; - auto error = mDisplayData[displayId].hwcDisplay->getActiveConfigIndex(&index); + auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index); if (error == HWC2::Error::BadConfig) { LOG_DISPLAY_ERROR(displayId, "No active config"); return -1; @@ -358,17 +339,17 @@ int HWComposer::getActiveConfigIndex(int32_t displayId) const { return index; } -std::vector<ui::ColorMode> HWComposer::getColorModes(int32_t displayId) const { +std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); std::vector<ui::ColorMode> modes; - auto error = mDisplayData[displayId].hwcDisplay->getColorModes(&modes); + auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes); RETURN_IF_HWC_ERROR(error, displayId, {}); return modes; } -status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode, - ui::RenderIntent renderIntent) { +status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode, + ui::RenderIntent renderIntent) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; @@ -381,8 +362,7 @@ status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode, return NO_ERROR; } - -void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) { +void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) { RETURN_IF_INVALID_DISPLAY(displayId); auto& displayData = mDisplayData[displayId]; @@ -403,37 +383,30 @@ void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) { displayData.vsyncEnabled = enabled; - char tag[16]; - snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", displayId); - ATRACE_INT(tag, enabled == HWC2::Vsync::Enable ? 1 : 0); + const auto tag = "HW_VSYNC_ON_" + std::to_string(displayId); + ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0); } } -status_t HWComposer::setClientTarget(int32_t displayId, uint32_t slot, - const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target, - ui::Dataspace dataspace) { +status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot, + const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target, + ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); - ALOGV("setClientTarget for display %d", displayId); + ALOGV("setClientTarget for display %" PRIu64, displayId); auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace); RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); return NO_ERROR; } -status_t HWComposer::prepare(DisplayDevice& display, - std::vector<CompositionInfo>& compositionData) { +status_t HWComposer::prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData) { ATRACE_CALL(); - Mutex::Autolock _l(mDisplayLock); - const auto displayId = display.getId(); - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { - ALOGV("Skipping HWComposer prepare for non-HWC display"); - return NO_ERROR; - } - RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + Mutex::Autolock _l(mDisplayLock); + auto& displayData = mDisplayData[displayId]; auto& hwcDisplay = displayData.hwcDisplay; if (!hwcDisplay->isConnected()) { @@ -503,7 +476,8 @@ status_t HWComposer::prepare(DisplayDevice& display, changedTypes[&*hwcLayer]); compositionInfo.compositionType = changedTypes[&*hwcLayer]; compositionInfo.layer->mLayer->setCompositionType(displayId, - compositionInfo.compositionType, false); + compositionInfo.compositionType, + false); } switch (compositionInfo.compositionType) { @@ -542,49 +516,48 @@ status_t HWComposer::prepare(DisplayDevice& display, return NO_ERROR; } -bool HWComposer::hasDeviceComposition(int32_t displayId) const { - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { +bool HWComposer::hasDeviceComposition(const std::optional<DisplayId>& displayId) const { + if (!displayId) { // Displays without a corresponding HWC display are never composed by // the device return false; } - RETURN_IF_INVALID_DISPLAY(displayId, false); - return mDisplayData[displayId].hasDeviceComposition; + RETURN_IF_INVALID_DISPLAY(*displayId, false); + return mDisplayData.at(*displayId).hasDeviceComposition; } -bool HWComposer::hasFlipClientTargetRequest(int32_t displayId) const { - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { +bool HWComposer::hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const { + if (!displayId) { // Displays without a corresponding HWC display are never composed by // the device return false; } - RETURN_IF_INVALID_DISPLAY(displayId, false); - return ((static_cast<uint32_t>(mDisplayData[displayId].displayRequests) & + RETURN_IF_INVALID_DISPLAY(*displayId, false); + return ((static_cast<uint32_t>(mDisplayData.at(*displayId).displayRequests) & static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0); } -bool HWComposer::hasClientComposition(int32_t displayId) const { - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { +bool HWComposer::hasClientComposition(const std::optional<DisplayId>& displayId) const { + if (!displayId) { // Displays without a corresponding HWC display are always composed by // the client return true; } - RETURN_IF_INVALID_DISPLAY(displayId, true); - return mDisplayData[displayId].hasClientComposition; + RETURN_IF_INVALID_DISPLAY(*displayId, true); + return mDisplayData.at(*displayId).hasClientComposition; } -sp<Fence> HWComposer::getPresentFence(int32_t displayId) const { +sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); - return mDisplayData[displayId].lastPresentFence; + return mDisplayData.at(displayId).lastPresentFence; } -sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId, - HWC2::Layer* layer) const { +sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const { RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); - auto displayFences = mDisplayData[displayId].releaseFences; + auto displayFences = mDisplayData.at(displayId).releaseFences; if (displayFences.count(layer) == 0) { ALOGV("getLayerReleaseFence: Release fence not found"); return Fence::NO_FENCE; @@ -592,7 +565,7 @@ sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId, return displayFences[layer]; } -status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) { +status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { ATRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -620,8 +593,7 @@ status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) { return NO_ERROR; } -status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) { - ALOGV("setPowerMode(%d, %d)", displayId, intMode); +status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto& displayData = mDisplayData[displayId]; @@ -677,7 +649,7 @@ status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) { return NO_ERROR; } -status_t HWComposer::setActiveConfig(int32_t displayId, size_t configId) { +status_t HWComposer::setActiveConfig(DisplayId displayId, size_t configId) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; @@ -691,8 +663,7 @@ status_t HWComposer::setActiveConfig(int32_t displayId, size_t configId) { return NO_ERROR; } -status_t HWComposer::setColorTransform(int32_t displayId, - const mat4& transform) { +status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; @@ -704,26 +675,34 @@ status_t HWComposer::setColorTransform(int32_t displayId, return NO_ERROR; } -void HWComposer::disconnectDisplay(int32_t displayId) { +void HWComposer::disconnectDisplay(DisplayId 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) { - mFreeDisplaySlots.insert(displayId); + mFreeVirtualDisplayIds.insert(displayId); ++mRemainingHwcVirtualDisplays; } const auto hwcDisplayId = displayData.hwcDisplay->getId(); - mHwcDisplaySlots.erase(hwcDisplayId); - displayData = DisplayData(); + mPhysicalDisplayIdMap.erase(hwcDisplayId); + mDisplayData.erase(displayId); + mVSyncCounts.erase(displayId); + + // TODO(b/74619554): Select internal/external display from remaining displays. + if (hwcDisplayId == mInternalHwcDisplayId) { + mInternalHwcDisplayId.reset(); + } else if (hwcDisplayId == mExternalHwcDisplayId) { + mExternalHwcDisplayId.reset(); + } mHwcDevice->destroyDisplay(hwcDisplayId); } -status_t HWComposer::setOutputBuffer(int32_t displayId, - const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) { +status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& buffer) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto& displayData = mDisplayData[displayId]; @@ -737,13 +716,12 @@ status_t HWComposer::setOutputBuffer(int32_t displayId, return NO_ERROR; } -void HWComposer::clearReleaseFences(int32_t displayId) { +void HWComposer::clearReleaseFences(DisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId); mDisplayData[displayId].releaseFences.clear(); } -status_t HWComposer::getHdrCapabilities( - int32_t displayId, HdrCapabilities* outCapabilities) { +status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; @@ -752,22 +730,22 @@ status_t HWComposer::getHdrCapabilities( return NO_ERROR; } -int32_t HWComposer::getSupportedPerFrameMetadata(int32_t displayId) const { +int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, 0); - return mDisplayData[displayId].hwcDisplay->getSupportedPerFrameMetadata(); + return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata(); } -std::vector<ui::RenderIntent> HWComposer::getRenderIntents(int32_t displayId, - ui::ColorMode colorMode) const { +std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId, + ui::ColorMode colorMode) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); std::vector<ui::RenderIntent> renderIntents; - auto error = mDisplayData[displayId].hwcDisplay->getRenderIntents(colorMode, &renderIntents); + auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents); RETURN_IF_HWC_ERROR(error, displayId, {}); return renderIntents; } -mat4 HWComposer::getDataspaceSaturationMatrix(int32_t displayId, ui::Dataspace dataspace) { +mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, {}); mat4 matrix; @@ -808,12 +786,67 @@ void HWComposer::dump(String8& result) const { result.append(mHwcDevice->dump().c_str()); } -std::optional<hwc2_display_t> -HWComposer::getHwcDisplayId(int32_t displayId) const { - if (!isValidDisplay(displayId)) { +std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const { + if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId); + it != mPhysicalDisplayIdMap.end()) { + return it->second; + } + return {}; +} + +std::optional<hwc2_display_t> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const { + if (const auto it = mDisplayData.find(displayId); + it != mDisplayData.end() && !it->second.isVirtual) { + return it->second.hwcDisplay->getId(); + } + return {}; +} + +std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) { + if (isUsingVrComposer() && mInternalHwcDisplayId) { + ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); + return {}; + } + + uint8_t port; + DisplayIdentificationData data; + const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data); + + if (mPhysicalDisplayIdMap.empty()) { + mHasMultiDisplaySupport = hasMultiDisplaySupport; + ALOGI("Switching to %s multi-display mode", + hasMultiDisplaySupport ? "generalized" : "legacy"); + } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) { + ALOGE("Ignoring connection of display %" PRIu64 " without identification data", + hwcDisplayId); return {}; } - return mDisplayData[displayId].hwcDisplay->getId(); + + std::optional<DisplayIdentificationInfo> info; + + if (mHasMultiDisplaySupport) { + info = parseDisplayIdentificationData(port, data); + ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId); + } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) { + ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId); + return {}; + } else { + ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64, + hwcDisplayId); + port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY; + } + + if (!mInternalHwcDisplayId) { + mInternalHwcDisplayId = hwcDisplayId; + } else if (!mExternalHwcDisplayId) { + mExternalHwcDisplayId = hwcDisplayId; + } + + if (info) return info; + + return DisplayIdentificationInfo{getFallbackDisplayId(port), + hwcDisplayId == mInternalHwcDisplayId ? "Internal display" + : "External display"}; } } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 5aa718550..5074c2c49 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -34,7 +34,8 @@ #include <memory> #include <optional> -#include <set> +#include <unordered_map> +#include <unordered_set> #include <vector> #include "DisplayIdentification.h" @@ -82,101 +83,94 @@ public: bool hasCapability(HWC2::Capability capability) const; - // Attempts to allocate a virtual display. If the virtual display is created - // on the HWC device, outId will contain its HWC ID. - status_t allocateVirtualDisplay(uint32_t width, uint32_t height, - ui::PixelFormat* format, int32_t* outId); + // Attempts to allocate a virtual display and returns its ID if created on the HWC device. + std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, + ui::PixelFormat* format); // Attempts to create a new layer on this display - HWC2::Layer* createLayer(int32_t displayId); + HWC2::Layer* createLayer(DisplayId displayId); // Destroy a previously created layer - void destroyLayer(int32_t displayId, HWC2::Layer* layer); + void destroyLayer(DisplayId displayId, HWC2::Layer* layer); // Asks the HAL what it can do - status_t prepare(DisplayDevice& display, - std::vector<CompositionInfo>& compositionData); + status_t prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData); - status_t setClientTarget(int32_t displayId, uint32_t slot, - const sp<Fence>& acquireFence, - const sp<GraphicBuffer>& target, ui::Dataspace dataspace); + status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& target, ui::Dataspace dataspace); // Present layers to the display and read releaseFences. - status_t presentAndGetReleaseFences(int32_t displayId); + status_t presentAndGetReleaseFences(DisplayId displayId); // set power mode - status_t setPowerMode(int32_t displayId, int mode); + status_t setPowerMode(DisplayId displayId, int mode); // set active config - status_t setActiveConfig(int32_t displayId, size_t configId); + status_t setActiveConfig(DisplayId displayId, size_t configId); // Sets a color transform to be applied to the result of composition - status_t setColorTransform(int32_t displayId, const mat4& transform); + status_t setColorTransform(DisplayId displayId, const mat4& transform); // reset state when an external, non-virtual display is disconnected - void disconnectDisplay(int32_t displayId); + void disconnectDisplay(DisplayId displayId); // does this display have layers handled by HWC - bool hasDeviceComposition(int32_t displayId) const; + bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const; // does this display have pending request to flip client target - bool hasFlipClientTargetRequest(int32_t displayId) const; + bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const; // does this display have layers handled by GLES - bool hasClientComposition(int32_t displayId) const; + bool hasClientComposition(const std::optional<DisplayId>& displayId) const; // get the present fence received from the last call to present. - sp<Fence> getPresentFence(int32_t displayId) const; + sp<Fence> getPresentFence(DisplayId displayId) const; // Get last release fence for the given layer - sp<Fence> getLayerReleaseFence(int32_t displayId, - HWC2::Layer* layer) const; + sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const; // Set the output buffer and acquire fence for a virtual display. // Returns INVALID_OPERATION if displayId is not a virtual display. - status_t setOutputBuffer(int32_t displayId, const sp<Fence>& acquireFence, - const sp<GraphicBuffer>& buf); + status_t setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& buffer); // After SurfaceFlinger has retrieved the release fences for all the frames, // it can call this to clear the shared pointers in the release fence map - void clearReleaseFences(int32_t displayId); + void clearReleaseFences(DisplayId displayId); // Fetches the HDR capabilities of the given display - status_t getHdrCapabilities(int32_t displayId, HdrCapabilities* outCapabilities); + status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities); - int32_t getSupportedPerFrameMetadata(int32_t displayId) const; + int32_t getSupportedPerFrameMetadata(DisplayId displayId) const; // Returns the available RenderIntent of the given display. - std::vector<ui::RenderIntent> getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const; + std::vector<ui::RenderIntent> getRenderIntents(DisplayId displayId, + ui::ColorMode colorMode) const; - mat4 getDataspaceSaturationMatrix(int32_t displayId, ui::Dataspace dataspace); + mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace); // Events handling --------------------------------------------------------- - // Returns true if successful, false otherwise. The - // DisplayDevice::DisplayType of the display is returned as an output param. - bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplay); - std::optional<DisplayId> onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType, - HWC2::Connection connection); + // Returns stable display ID (and display name on connection of new or previously disconnected + // display), or std::nullopt if hotplug event was ignored. + std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId, + HWC2::Connection connection); - void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled); + bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp); + void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled); - // Query display parameters. Pass in a display index (e.g. - // HWC_DISPLAY_PRIMARY). - nsecs_t getRefreshTimestamp(int32_t displayId) const; - bool isConnected(int32_t displayId) const; + nsecs_t getRefreshTimestamp(DisplayId displayId) const; + bool isConnected(DisplayId displayId) const; // Non-const because it can update configMap inside of mDisplayData - std::vector<std::shared_ptr<const HWC2::Display::Config>> - getConfigs(int32_t displayId) const; + std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(DisplayId displayId) const; - std::shared_ptr<const HWC2::Display::Config> - getActiveConfig(int32_t displayId) const; - int getActiveConfigIndex(int32_t displayId) const; + std::shared_ptr<const HWC2::Display::Config> getActiveConfig(DisplayId displayId) const; + int getActiveConfigIndex(DisplayId displayId) const; - std::vector<ui::ColorMode> getColorModes(int32_t displayId) const; + std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const; - status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode, - ui::RenderIntent renderIntent); + status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode, + ui::RenderIntent renderIntent); bool isUsingVrComposer() const; @@ -185,12 +179,19 @@ public: android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); } - std::optional<hwc2_display_t> getHwcDisplayId(int32_t displayId) const; + // TODO(b/74619554): Remove special cases for internal/external display. + std::optional<hwc2_display_t> getInternalHwcDisplayId() const { return mInternalHwcDisplayId; } + std::optional<hwc2_display_t> getExternalHwcDisplayId() const { return mExternalHwcDisplayId; } + + std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const; + std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const; + private: // For unit tests friend TestableSurfaceFlinger; - bool isValidDisplay(int32_t displayId) const; + std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId); + static void validateChange(HWC2::Composition from, HWC2::Composition to); struct cb_context; @@ -215,25 +216,30 @@ private: HWC2::Error presentError; }; - std::vector<DisplayData> mDisplayData{HWC_NUM_PHYSICAL_DISPLAY_TYPES}; + std::unordered_map<DisplayId, DisplayData> mDisplayData; // This must be destroyed before mDisplayData, because destructor may call back into HWComposer // and look up DisplayData. std::unique_ptr<HWC2::Device> mHwcDevice; - std::set<size_t> mFreeDisplaySlots; - std::unordered_map<hwc2_display_t, int32_t> mHwcDisplaySlots; + std::unordered_map<hwc2_display_t, DisplayId> mPhysicalDisplayIdMap; + std::optional<hwc2_display_t> mInternalHwcDisplayId; + std::optional<hwc2_display_t> mExternalHwcDisplayId; + bool mHasMultiDisplaySupport = false; + // protect mDisplayData from races between prepare and dump mutable Mutex mDisplayLock; cb_context* mCBContext = nullptr; - size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES]{0, 0}; + std::unordered_map<DisplayId, size_t> mVSyncCounts; + + std::unordered_set<uint32_t> mFreeVirtualDisplayIds; + uint32_t mNextVirtualDisplayId = 0; uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()}; // protected by mLock mutable Mutex mLock; - mutable std::unordered_map<int32_t, nsecs_t> mLastHwVSync{ - {{HWC_DISPLAY_PRIMARY, 0}, {HWC_DISPLAY_EXTERNAL, 0}}}; + mutable std::unordered_map<DisplayId, nsecs_t> mLastHwVSync; // thread-safe mutable Mutex mVsyncLock; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index c111a27f5..27d3dc560 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -48,34 +48,34 @@ static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) { } } -VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, - const sp<IGraphicBufferProducer>& sink, - const sp<IGraphicBufferProducer>& bqProducer, - const sp<IGraphicBufferConsumer>& bqConsumer, - const std::string& name) -: ConsumerBase(bqConsumer), - mHwc(hwc), - mDisplayId(dispId), - mDisplayName(name), - mSource{}, - mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), - mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), - mOutputUsage(GRALLOC_USAGE_HW_COMPOSER), - mProducerSlotSource(0), - mProducerBuffers(), - mQueueBufferOutput(), - mSinkBufferWidth(0), - mSinkBufferHeight(0), - mCompositionType(COMPOSITION_UNKNOWN), - mFbFence(Fence::NO_FENCE), - mOutputFence(Fence::NO_FENCE), - mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), - mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), - mDbgState(DBG_STATE_IDLE), - mDbgLastCompositionType(COMPOSITION_UNKNOWN), - mMustRecompose(false), - mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) -{ +VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, + const std::optional<DisplayId>& displayId, + const sp<IGraphicBufferProducer>& sink, + const sp<IGraphicBufferProducer>& bqProducer, + const sp<IGraphicBufferConsumer>& bqConsumer, + const std::string& name) + : ConsumerBase(bqConsumer), + mHwc(hwc), + mDisplayId(displayId), + mDisplayName(name), + mSource{}, + mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), + mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), + mOutputUsage(GRALLOC_USAGE_HW_COMPOSER), + mProducerSlotSource(0), + mProducerBuffers(), + mQueueBufferOutput(), + mSinkBufferWidth(0), + mSinkBufferHeight(0), + mCompositionType(COMPOSITION_UNKNOWN), + mFbFence(Fence::NO_FENCE), + mOutputFence(Fence::NO_FENCE), + mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), + mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), + mDbgState(DBG_STATE_IDLE), + mDbgLastCompositionType(COMPOSITION_UNKNOWN), + mMustRecompose(false), + mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) { mSource[SOURCE_SINK] = sink; mSource[SOURCE_SCRATCH] = bqProducer; @@ -116,8 +116,9 @@ VirtualDisplaySurface::~VirtualDisplaySurface() { } status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { - if (mDisplayId < 0) + if (!mDisplayId) { return NO_ERROR; + } mMustRecompose = mustRecompose; @@ -129,8 +130,9 @@ status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { } status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { - if (mDisplayId < 0) + if (!mDisplayId) { return NO_ERROR; + } VDS_LOGW_IF(mDbgState != DBG_STATE_BEGUN, "Unexpected prepareFrame() in %s state", dbgStateStr()); @@ -177,8 +179,9 @@ status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { } status_t VirtualDisplaySurface::advanceFrame() { - if (mDisplayId < 0) + if (!mDisplayId) { return NO_ERROR; + } if (mCompositionType == COMPOSITION_HWC) { VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED, @@ -211,7 +214,7 @@ status_t VirtualDisplaySurface::advanceFrame() { // At this point we know the output buffer acquire fence, // so update HWC state with it. - mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer); + mHwc.setOutputBuffer(*mDisplayId, mOutputFence, outBuffer); status_t result = NO_ERROR; if (fbBuffer != nullptr) { @@ -221,22 +224,23 @@ status_t VirtualDisplaySurface::advanceFrame() { &hwcSlot, &hwcBuffer); // TODO: Correctly propagate the dataspace from GL composition - result = mHwc.setClientTarget(mDisplayId, hwcSlot, mFbFence, - hwcBuffer, ui::Dataspace::UNKNOWN); + result = mHwc.setClientTarget(*mDisplayId, hwcSlot, mFbFence, hwcBuffer, + ui::Dataspace::UNKNOWN); } return result; } void VirtualDisplaySurface::onFrameCommitted() { - if (mDisplayId < 0) + if (!mDisplayId) { return; + } VDS_LOGW_IF(mDbgState != DBG_STATE_HWC, "Unexpected onFrameCommitted() in %s state", dbgStateStr()); mDbgState = DBG_STATE_IDLE; - sp<Fence> retireFence = mHwc.getPresentFence(mDisplayId); + sp<Fence> retireFence = mHwc.getPresentFence(*mDisplayId); if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) { // release the scratch buffer back to the pool Mutex::Autolock lock(mMutex); @@ -291,8 +295,9 @@ const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const { status_t VirtualDisplaySurface::requestBuffer(int pslot, sp<GraphicBuffer>* outBuf) { - if (mDisplayId < 0) + if (!mDisplayId) { return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf); + } VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, "Unexpected requestBuffer pslot=%d in %s state", @@ -313,7 +318,7 @@ status_t VirtualDisplaySurface::setAsyncMode(bool async) { status_t VirtualDisplaySurface::dequeueBuffer(Source source, PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) { - LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId); + LOG_FATAL_IF(!mDisplayId); status_t result = mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight, @@ -359,7 +364,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, uint PixelFormat format, uint64_t usage, uint64_t* outBufferAge, FrameEventHistoryDelta* outTimestamps) { - if (mDisplayId < 0) { + if (!mDisplayId) { return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge, outTimestamps); } @@ -446,8 +451,9 @@ status_t VirtualDisplaySurface::attachBuffer(int* /* outSlot */, status_t VirtualDisplaySurface::queueBuffer(int pslot, const QueueBufferInput& input, QueueBufferOutput* output) { - if (mDisplayId < 0) + if (!mDisplayId) { return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output); + } VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, "Unexpected queueBuffer(pslot=%d) in %s state", pslot, @@ -504,8 +510,9 @@ status_t VirtualDisplaySurface::queueBuffer(int pslot, status_t VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) { - if (mDisplayId < 0) + if (!mDisplayId) { return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence); + } VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, "Unexpected cancelBuffer(pslot=%d) in %s state", pslot, @@ -616,6 +623,8 @@ void VirtualDisplaySurface::resetPerFrameState() { } status_t VirtualDisplaySurface::refreshOutputBuffer() { + LOG_FATAL_IF(!mDisplayId); + if (mOutputProducerSlot >= 0) { mSource[SOURCE_SINK]->cancelBuffer( mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot), @@ -633,8 +642,8 @@ status_t VirtualDisplaySurface::refreshOutputBuffer() { // until after GLES calls queueBuffer(). So here we just set the buffer // (for use in HWC prepare) but not the fence; we'll call this again with // the proper fence once we have it. - result = mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE, - mProducerBuffers[mOutputProducerSlot]); + result = mHwc.setOutputBuffer(*mDisplayId, Fence::NO_FENCE, + mProducerBuffers[mOutputProducerSlot]); return result; } diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 4bd4d0fe6..33678df96 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -17,8 +17,10 @@ #ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H #define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H +#include <optional> #include <string> +#include "DisplayIdentification.h" #include "DisplaySurface.h" #include "HWComposerBufferCache.h" @@ -75,11 +77,10 @@ class VirtualDisplaySurface : public DisplaySurface, public BnGraphicBufferProducer, private ConsumerBase { public: - VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, - const sp<IGraphicBufferProducer>& sink, - const sp<IGraphicBufferProducer>& bqProducer, - const sp<IGraphicBufferConsumer>& bqConsumer, - const std::string& name); + VirtualDisplaySurface(HWComposer& hwc, const std::optional<DisplayId>& displayId, + const sp<IGraphicBufferProducer>& sink, + const sp<IGraphicBufferProducer>& bqProducer, + const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name); // // DisplaySurface interface @@ -154,7 +155,7 @@ private: // Immutable after construction // HWComposer& mHwc; - const int32_t mDisplayId; + const std::optional<DisplayId> mDisplayId; const std::string mDisplayName; sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_* uint32_t mDefaultOutputFormat; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f29dfc0f1..f41a753a7 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -196,9 +196,9 @@ sp<IBinder> Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) { +bool Layer::createHwcLayer(HWComposer* hwc, DisplayId displayId) { LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, - "Already have a layer for display %d", displayId); + "Already have a layer for display %" PRIu64, displayId); auto layer = std::shared_ptr<HWC2::Layer>( hwc->createLayer(displayId), [hwc, displayId](HWC2::Layer* layer) { @@ -214,7 +214,7 @@ bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) { return true; } -bool Layer::destroyHwcLayer(int32_t displayId) { +bool Layer::destroyHwcLayer(DisplayId displayId) { if (getBE().mHwcLayers.count(displayId) == 0) { return false; } @@ -461,12 +461,13 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const { void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) { const auto displayId = display->getId(); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setGeometry: no HWC layer found (%d)", - mName.string(), displayId); + LOG_ALWAYS_FATAL_IF(!displayId); + if (!hasHwcLayer(*displayId)) { + ALOGE("[%s] failed to setGeometry: no HWC layer found for display %" PRIu64, mName.string(), + *displayId); return; } - auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcInfo = getBE().mHwcLayers[*displayId]; // enable this layer hwcInfo.forceClientComposition = false; @@ -618,7 +619,7 @@ void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) { if (orientation & ui::Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; - getBE().mHwcLayers[displayId].compositionType = HWC2::Composition::Client; + getBE().mHwcLayers[*displayId].compositionType = HWC2::Composition::Client; } else { auto transform = static_cast<HWC2::Transform>(orientation); hwcInfo.transform = transform; @@ -632,18 +633,18 @@ void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) { } } -void Layer::forceClientComposition(int32_t displayId) { +void Layer::forceClientComposition(DisplayId displayId) { if (getBE().mHwcLayers.count(displayId) == 0) { - ALOGE("forceClientComposition: no HWC layer found (%d)", displayId); + ALOGE("forceClientComposition: no HWC layer found (display %" PRIu64 ")", displayId); return; } getBE().mHwcLayers[displayId].forceClientComposition = true; } -bool Layer::getForceClientComposition(int32_t displayId) { +bool Layer::getForceClientComposition(DisplayId displayId) { if (getBE().mHwcLayers.count(displayId) == 0) { - ALOGE("getForceClientComposition: no HWC layer found (%d)", displayId); + ALOGE("getForceClientComposition: no HWC layer found (display %" PRIu64 ")", displayId); return false; } @@ -652,7 +653,7 @@ bool Layer::getForceClientComposition(int32_t displayId) { void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) { const auto displayId = display->getId(); - if (getBE().mHwcLayers.count(displayId) == 0 || + if (getBE().mHwcLayers.count(*displayId) == 0 || getCompositionType(displayId) != HWC2::Composition::Cursor) { return; } @@ -675,8 +676,8 @@ void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) { auto position = displayTransform.transform(frame); auto error = - (getBE().mHwcLayers[displayId].layer)->setCursorPosition( - position.left, position.top); + getBE().mHwcLayers[*displayId].layer->setCursorPosition(position.left, position.top); + ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " "to (%d, %d): %s (%d)", @@ -708,7 +709,7 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0, 0, 0, 0); } -void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc) { +void Layer::setCompositionType(DisplayId displayId, HWC2::Composition type, bool callIntoHwc) { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; @@ -731,16 +732,20 @@ void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool c } } -HWC2::Composition Layer::getCompositionType(int32_t displayId) const { - if (getBE().mHwcLayers.count(displayId) == 0) { +HWC2::Composition Layer::getCompositionType(const std::optional<DisplayId>& displayId) const { + if (!displayId) { // If we're querying the composition type for a display that does not // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - return getBE().mHwcLayers[displayId].compositionType; + if (getBE().mHwcLayers.count(*displayId) == 0) { + ALOGE("getCompositionType called with an invalid HWC layer"); + return HWC2::Composition::Invalid; + } + return getBE().mHwcLayers.at(*displayId).compositionType; } -void Layer::setClearClientTarget(int32_t displayId, bool clear) { +void Layer::setClearClientTarget(DisplayId displayId, bool clear) { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setClearClientTarget called without a valid HWC layer"); return; @@ -748,7 +753,7 @@ void Layer::setClearClientTarget(int32_t displayId, bool clear) { getBE().mHwcLayers[displayId].clearClientTarget = clear; } -bool Layer::getClearClientTarget(int32_t displayId) const { +bool Layer::getClearClientTarget(DisplayId displayId) const { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("getClearClientTarget called without a valid HWC layer"); return false; @@ -1416,7 +1421,7 @@ void Layer::miniDumpHeader(String8& result) { result.append("-----------------------------\n"); } -void Layer::miniDump(String8& result, int32_t displayId) const { +void Layer::miniDump(String8& result, DisplayId displayId) const { if (getBE().mHwcLayers.count(displayId) == 0) { return; } @@ -1980,7 +1985,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) } } -void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) { +void Layer::writeToProto(LayerProto* layerInfo, DisplayId displayId) { if (!hasHwcLayer(displayId)) { return; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6921ca9b0..ced653250 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -38,6 +38,7 @@ #include <cstdint> #include <list> +#include <optional> #include <vector> #include "Client.h" @@ -351,7 +352,7 @@ public: void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); - void writeToProto(LayerProto* layerInfo, int32_t displayId); + void writeToProto(LayerProto* layerInfo, DisplayId displayId); virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; } virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; } @@ -377,16 +378,17 @@ public: virtual bool isHdrY410() const { return false; } void setGeometry(const sp<const DisplayDevice>& display, uint32_t z); - void forceClientComposition(int32_t displayId); - bool getForceClientComposition(int32_t displayId); - virtual void setPerFrameData(const sp<const DisplayDevice>& display) = 0; + void forceClientComposition(DisplayId displayId); + bool getForceClientComposition(DisplayId displayId); + virtual void setPerFrameData(DisplayId displayId, const ui::Transform& transform, + const Rect& viewport, int32_t supportedPerFrameMetadata) = 0; // callIntoHwc exists so we can update our local state and call // acceptDisplayChanges without unnecessarily updating the device's state - void setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc = true); - HWC2::Composition getCompositionType(int32_t displayId) const; - void setClearClientTarget(int32_t displayId, bool clear); - bool getClearClientTarget(int32_t displayId) const; + void setCompositionType(DisplayId displayId, HWC2::Composition type, bool callIntoHwc = true); + HWC2::Composition getCompositionType(const std::optional<DisplayId>& displayId) const; + void setClearClientTarget(DisplayId displayId, bool clear); + bool getClearClientTarget(DisplayId displayId) const; void updateCursorPosition(const sp<const DisplayDevice>& display); /* @@ -407,7 +409,8 @@ public: * called after composition. * returns true if the layer latched a new buffer this frame. */ - virtual bool onPostComposition(const std::shared_ptr<FenceTime>& /*glDoneFence*/, + virtual bool onPostComposition(const std::optional<DisplayId>& /*displayId*/, + const std::shared_ptr<FenceTime>& /*glDoneFence*/, const std::shared_ptr<FenceTime>& /*presentFence*/, const CompositorTiming& /*compositorTiming*/) { return false; @@ -492,24 +495,24 @@ public: // ----------------------------------------------------------------------- - bool createHwcLayer(HWComposer* hwc, int32_t displayId); - bool destroyHwcLayer(int32_t displayId); + bool createHwcLayer(HWComposer* hwc, DisplayId displayId); + bool destroyHwcLayer(DisplayId displayId); void destroyAllHwcLayers(); - bool hasHwcLayer(int32_t displayId) { return getBE().mHwcLayers.count(displayId) > 0; } + bool hasHwcLayer(DisplayId displayId) { return getBE().mHwcLayers.count(displayId) > 0; } - HWC2::Layer* getHwcLayer(int32_t displayId) { - if (getBE().mHwcLayers.count(displayId) == 0) { + HWC2::Layer* getHwcLayer(DisplayId displayId) { + if (!hasHwcLayer(displayId)) { return nullptr; } return getBE().mHwcLayers[displayId].layer.get(); } - bool setHwcLayer(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { + bool setHwcLayer(DisplayId displayId) { + if (!hasHwcLayer(displayId)) { return false; } - getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[hwcId].layer; + getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[displayId].layer; return true; } @@ -524,7 +527,7 @@ public: /* always call base class first */ static void miniDumpHeader(String8& result); - void miniDump(String8& result, int32_t displayId) const; + void miniDump(String8& result, DisplayId displayId) const; void dumpFrameStats(String8& result) const; void dumpFrameEvents(String8& result); void clearFrameStats(); diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 463c46c28..3f5134ecd 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -24,6 +24,7 @@ #include <renderengine/Texture.h> #include <ui/Region.h> +#include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" #include "SurfaceFlinger.h" @@ -41,7 +42,7 @@ struct CompositionInfo { std::shared_ptr<LayerBE> layer; struct { std::shared_ptr<HWC2::Layer> hwcLayer; - int32_t displayId = -1; + DisplayId displayId; sp<Fence> fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; Rect displayFrame; @@ -123,12 +124,11 @@ private: HWC2::Transform transform; }; - // A layer can be attached to multiple displays when operating in mirror mode // (a.k.a: when several displays are attached with equal layerStack). In this // case we need to keep track. In non-mirror mode, a layer will have only one - // HWCInfo. This map key is a display layerStack. - std::unordered_map<int32_t, HWCInfo> mHwcLayers; + // HWCInfo. + std::unordered_map<DisplayId, HWCInfo> mHwcLayers; CompositionInfo compositionInfo; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dec08fd62..137d91bf2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -105,8 +105,6 @@ #include <layerproto/LayerProtoParser.h> -#define DISPLAY_COUNT 1 - namespace android { using namespace android::hardware::configstore; @@ -247,7 +245,6 @@ SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory, mLayersRemoved(false), mLayersAdded(false), mBootTime(systemTime()), - mDisplayTokens(), mVisibleRegionsDirty(false), mGeometryInvalid(false), mAnimCompositionPending(false), @@ -482,40 +479,49 @@ sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, sp<BBinder> token = new DisplayToken(this); Mutex::Autolock _l(mStateLock); - DisplayDeviceState info; - info.type = DisplayDevice::DISPLAY_VIRTUAL; - info.displayName = displayName; - info.isSecure = secure; - mCurrentState.displays.add(token, info); - mInterceptor->saveDisplayCreation(info); + // Display ID is assigned when virtual display is allocated by HWC. + DisplayDeviceState state; + state.isSecure = secure; + state.displayName = displayName; + mCurrentState.displays.add(token, state); + mInterceptor->saveDisplayCreation(state); return token; } void SurfaceFlinger::destroyDisplay(const sp<IBinder>& displayToken) { Mutex::Autolock _l(mStateLock); - ssize_t idx = mCurrentState.displays.indexOfKey(displayToken); - if (idx < 0) { + ssize_t index = mCurrentState.displays.indexOfKey(displayToken); + if (index < 0) { ALOGE("destroyDisplay: Invalid display token %p", displayToken.get()); return; } - const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); - if (!info.isVirtual()) { + const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); + if (!state.isVirtual()) { ALOGE("destroyDisplay called for non-virtual display"); return; } - mInterceptor->saveDisplayDeletion(info.sequenceId); - mCurrentState.displays.removeItemsAt(idx); + mInterceptor->saveDisplayDeletion(state.sequenceId); + mCurrentState.displays.removeItemsAt(index); setTransactionFlags(eDisplayTransactionNeeded); } sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) { - if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { - ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id); + std::optional<DisplayId> displayId; + + if (id == HWC_DISPLAY_PRIMARY) { + displayId = getInternalDisplayId(); + } else if (id == HWC_DISPLAY_EXTERNAL) { + displayId = getExternalDisplayId(); + } + + if (!displayId) { + ALOGE("%s: Invalid display %d", __FUNCTION__, id); return nullptr; } - return mDisplayTokens[id]; + + return getPhysicalDisplayToken(*displayId); } status_t SurfaceFlinger::getColorManagement(bool* outGetColorManagement) const { @@ -598,8 +604,10 @@ void SurfaceFlinger::init() { // start the EventThread if (mUseScheduler) { - mScheduler = getFactory().createScheduler( - [this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); }); + mScheduler = getFactory().createScheduler([this](bool enabled) { + setVsyncEnabled(EventThread::DisplayType::Primary, enabled); + }); + mAppConnectionHandle = mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs, [this] { resyncWithRateLimit(); }, @@ -659,7 +667,7 @@ void SurfaceFlinger::init() { processDisplayHotplugEventsLocked(); const auto display = getDefaultDisplayDeviceLocked(); LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback."); - LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(display->getId()), + LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()), "Internal display is disconnected."); // make the default display GLContext current so that we can create textures @@ -682,7 +690,7 @@ void SurfaceFlinger::init() { }; mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(), getHwComposer() - .getHwcDisplayId(display->getId()) + .fromPhysicalDisplayId(*display->getId()) .value_or(0), vrFlingerRequestDisplayCallback); if (!mVrFlinger) { @@ -691,7 +699,7 @@ void SurfaceFlinger::init() { } mEventControlThread = getFactory().createEventControlThread( - [this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); }); + [this](bool enabled) { setVsyncEnabled(EventThread::DisplayType::Primary, enabled); }); // initialize our drawing state mDrawingState = mCurrentState; @@ -717,8 +725,8 @@ void SurfaceFlinger::init() { // and apply this saturation matrix on Display P3 content. Unless the risk of applying // such saturation matrix on Display P3 is understood fully, the API should always return // identify matrix. - mEnhancedSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(display->getId(), - Dataspace::SRGB_LINEAR); + mEnhancedSaturationMatrix = + getHwComposer().getDataspaceSaturationMatrix(*display->getId(), Dataspace::SRGB_LINEAR); // we will apply this on Display P3. if (mEnhancedSaturationMatrix != mat4()) { @@ -805,16 +813,9 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken, return BAD_VALUE; } - int32_t type = NAME_NOT_FOUND; - for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { - if (displayToken == mDisplayTokens[i]) { - type = i; - break; - } - } - - if (type < 0) { - return type; + const auto displayId = getPhysicalDisplayId(displayToken); + if (!displayId) { + return NAME_NOT_FOUND; } // TODO: Not sure if display density should handled by SF any longer @@ -838,7 +839,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken, ConditionalLock _l(mStateLock, std::this_thread::get_id() != mMainThreadId); - for (const auto& hwConfig : getHwComposer().getConfigs(type)) { + for (const auto& hwConfig : getHwComposer().getConfigs(*displayId)) { DisplayInfo info = DisplayInfo(); float xdpi = hwConfig->getDpiX(); @@ -850,7 +851,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken, info.viewportW = info.w; info.viewportH = info.h; - if (type == DisplayDevice::DISPLAY_PRIMARY) { + if (displayId == getInternalDisplayId()) { // The density of the device is provided by a build property float density = Density::getBuildDensity() / 160.0f; if (density == 0) { @@ -906,7 +907,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken, // All non-virtual displays are currently considered secure. info.secure = true; - if (type == DisplayDevice::DISPLAY_PRIMARY && + if (displayId == getInternalDisplayId() && primaryDisplayOrientation & DisplayState::eOrientationSwapMask) { std::swap(info.w, info.h); } @@ -922,7 +923,6 @@ status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>&, DisplayStatInfo* st return BAD_VALUE; } - // FIXME for now we always return stats for the primary display. if (mUseScheduler) { mScheduler->getDisplayStatInfo(stats); } else { @@ -943,18 +943,21 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { } void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& display, int mode) { - int currentMode = display->getActiveConfig(); - if (mode == currentMode) { + if (display->isVirtual()) { + ALOGE("%s: Invalid operation on virtual display", __FUNCTION__); return; } - if (display->isVirtual()) { - ALOGW("Trying to set config for virtual display"); + int currentMode = display->getActiveConfig(); + if (mode == currentMode) { return; } + const auto displayId = display->getId(); + LOG_ALWAYS_FATAL_IF(!displayId); + display->setActiveConfig(mode); - getHwComposer().setActiveConfig(display->getDisplayType(), mode); + getHwComposer().setActiveConfig(*displayId, mode); } status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) { @@ -979,29 +982,23 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mo return NO_ERROR; } + status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken, Vector<ColorMode>* outColorModes) { if (!displayToken || !outColorModes) { return BAD_VALUE; } - int32_t type = NAME_NOT_FOUND; - for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { - if (displayToken == mDisplayTokens[i]) { - type = i; - break; - } - } - - if (type < 0) { - return type; + const auto displayId = getPhysicalDisplayId(displayToken); + if (!displayId) { + return NAME_NOT_FOUND; } std::vector<ColorMode> modes; { ConditionalLock _l(mStateLock, std::this_thread::get_id() != mMainThreadId); - modes = getHwComposer().getColorModes(type); + modes = getHwComposer().getColorModes(*displayId); } outColorModes->clear(); std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes)); @@ -1018,6 +1015,11 @@ ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& displayToken) { void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& display, ColorMode mode, Dataspace dataSpace, RenderIntent renderIntent) { + if (display->isVirtual()) { + ALOGE("%s: Invalid operation on virtual display", __FUNCTION__); + return; + } + ColorMode currentMode = display->getActiveColorMode(); Dataspace currentDataSpace = display->getCompositionDataSpace(); RenderIntent currentRenderIntent = display->getActiveRenderIntent(); @@ -1027,19 +1029,17 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& display return; } - if (display->isVirtual()) { - ALOGW("Trying to set config for virtual display"); - return; - } - display->setActiveColorMode(mode); display->setCompositionDataSpace(dataSpace); display->setActiveRenderIntent(renderIntent); - getHwComposer().setActiveColorMode(display->getDisplayType(), mode, renderIntent); - ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), type=%d", + const auto displayId = display->getId(); + LOG_ALWAYS_FATAL_IF(!displayId); + getHwComposer().setActiveColorMode(*displayId, mode, renderIntent); + + ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), display=%" PRIu64, decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(), - renderIntent, display->getDisplayType()); + renderIntent, *displayId); } status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) { @@ -1255,12 +1255,12 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) { return; } - const auto displayId = DisplayDevice::DISPLAY_PRIMARY; - if (!getHwComposer().isConnected(displayId)) { + const auto displayId = getInternalDisplayId(); + if (!displayId || !getHwComposer().isConnected(*displayId)) { return; } - const auto activeConfig = getHwComposer().getActiveConfig(displayId); + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); const nsecs_t period = activeConfig->getVsyncPeriod(); if (mUseScheduler) { @@ -1311,12 +1311,11 @@ void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDispl return; } - int32_t type; - if (!getBE().mHwc->onVsync(hwcDisplayId, timestamp, &type)) { + if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) { return; } - if (type != DisplayDevice::DISPLAY_PRIMARY) { + if (hwcDisplayId != getHwComposer().getInternalHwcDisplayId()) { // For now, we don't do anything with external display vsyncs. return; } @@ -1379,11 +1378,13 @@ void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDispl repaintEverything(); } -void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) { +void SurfaceFlinger::setVsyncEnabled(EventThread::DisplayType /*displayType*/, bool enabled) { ATRACE_CALL(); Mutex::Autolock lock(mStateLock); - getHwComposer().setVsyncEnabled(disp, - enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable); + if (const auto displayId = getInternalDisplayId()) { + getHwComposer().setVsyncEnabled(*displayId, + enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable); + } } // Note: it is assumed the caller holds |mStateLock| when this is called @@ -1454,7 +1455,7 @@ void SurfaceFlinger::updateVrFlinger() { setPowerModeInternal(display, currentDisplayPowerMode, /*stateLockHeld*/ true); // Reset the timing values to account for the period of the swapped in HWC - const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); + const auto activeConfig = getHwComposer().getActiveConfig(*display->getId()); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); @@ -1595,24 +1596,25 @@ void SurfaceFlinger::calculateWorkingSet() { mGeometryInvalid = false; for (const auto& [token, display] : mDisplays) { const auto displayId = display->getId(); - if (displayId >= 0) { - const Vector<sp<Layer>>& currentLayers( - display->getVisibleLayersSortedByZ()); - for (size_t i = 0; i < currentLayers.size(); i++) { - const auto& layer = currentLayers[i]; - - if (!layer->hasHwcLayer(displayId)) { - if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) { - layer->forceClientComposition(displayId); - continue; - } - } + if (!displayId) { + continue; + } - layer->setGeometry(display, i); - if (mDebugDisableHWC || mDebugRegion) { - layer->forceClientComposition(displayId); + const Vector<sp<Layer>>& currentLayers = display->getVisibleLayersSortedByZ(); + for (size_t i = 0; i < currentLayers.size(); i++) { + const auto& layer = currentLayers[i]; + + if (!layer->hasHwcLayer(*displayId)) { + if (!layer->createHwcLayer(&getHwComposer(), *displayId)) { + layer->forceClientComposition(*displayId); + continue; } } + + layer->setGeometry(display, i); + if (mDebugDisableHWC || mDebugRegion) { + layer->forceClientComposition(*displayId); + } } } } @@ -1620,41 +1622,43 @@ void SurfaceFlinger::calculateWorkingSet() { // Set the per-frame data for (const auto& [token, display] : mDisplays) { const auto displayId = display->getId(); - if (displayId < 0) { + if (!displayId) { continue; } if (mDrawingState.colorMatrixChanged) { display->setColorTransform(mDrawingState.colorMatrix); - status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " - "display %d: %d", displayId, result); + status_t result = + getHwComposer().setColorTransform(*displayId, mDrawingState.colorMatrix); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %" PRIu64 ": %d", + *displayId, result); } for (auto& layer : display->getVisibleLayersSortedByZ()) { if (layer->isHdrY410()) { - layer->forceClientComposition(displayId); + layer->forceClientComposition(*displayId); } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && !display->hasHDR10Support()) { - layer->forceClientComposition(displayId); + layer->forceClientComposition(*displayId); } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && !display->hasHLGSupport()) { - layer->forceClientComposition(displayId); + layer->forceClientComposition(*displayId); } // TODO(b/111562338) remove when composer 2.3 is shipped. if (layer->hasColorTransform()) { - layer->forceClientComposition(displayId); + layer->forceClientComposition(*displayId); } - if (layer->getForceClientComposition(displayId)) { + if (layer->getForceClientComposition(*displayId)) { ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(displayId, HWC2::Composition::Client); + layer->setCompositionType(*displayId, HWC2::Composition::Client); continue; } - layer->setPerFrameData(display); + layer->setPerFrameData(*displayId, display->getTransform(), display->getViewport(), + display->getSupportedPerFrameMetadata()); } if (useColorManagement) { @@ -1674,10 +1678,14 @@ void SurfaceFlinger::calculateWorkingSet() { for (auto& layer : display->getVisibleLayersSortedByZ()) { const auto displayId = display->getId(); layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId); - if (!layer->setHwcLayer(displayId)) { - ALOGV("Need to create HWCLayer for %s", layer->getName().string()); + + if (displayId) { + if (!layer->setHwcLayer(*displayId)) { + ALOGV("Need to create HWCLayer for %s", layer->getName().string()); + } + layer->getBE().compositionInfo.hwc.displayId = *displayId; } - layer->getBE().compositionInfo.hwc.displayId = displayId; + getBE().mCompositionInfo[token].push_back(layer->getBE().compositionInfo); layer->getBE().compositionInfo.hwc.hwcLayer = nullptr; } @@ -1837,7 +1845,7 @@ void SurfaceFlinger::postComposition() getBE().mDisplayTimeline.updateSignalTimes(); mPreviousPresentFence = - display ? getHwComposer().getPresentFence(display->getId()) : Fence::NO_FENCE; + display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE; auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence); getBE().mDisplayTimeline.push(presentFenceTime); @@ -1860,8 +1868,8 @@ void SurfaceFlinger::postComposition() } mDrawingState.traverseInZOrder([&](Layer* layer) { - bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime, - presentFenceTime, compositorTiming); + bool frameLatched = layer->onPostComposition(display->getId(), glCompositionDoneFenceTime, + presentFenceTime, compositorTiming); if (frameLatched) { recordBufferingStats(layer->getName().string(), layer->getOccupancyHistory(false)); @@ -1881,7 +1889,7 @@ void SurfaceFlinger::postComposition() } if (!hasSyncFramework) { - if (display && getHwComposer().isConnected(display->getId()) && display->isPoweredOn()) { + if (display && getHwComposer().isConnected(*display->getId()) && display->isPoweredOn()) { if (mUseScheduler) { mScheduler->enableHardwareVsync(); } else { @@ -1896,10 +1904,10 @@ void SurfaceFlinger::postComposition() if (presentFenceTime->isValid()) { mAnimFrameTracker.setActualPresentFence( std::move(presentFenceTime)); - } else if (display && getHwComposer().isConnected(display->getId())) { + } else if (display && getHwComposer().isConnected(*display->getId())) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. - const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(display->getId()); + const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId()); mAnimFrameTracker.setActualPresentTime(presentTime); } mAnimFrameTracker.advanceFrame(); @@ -1912,8 +1920,7 @@ void SurfaceFlinger::postComposition() mTimeStats.setPresentFenceGlobal(presentFenceTime); - if (display && getHwComposer().isConnected(display->getId()) && - display->getPowerMode() == HWC_POWER_MODE_OFF) { + if (display && getHwComposer().isConnected(*display->getId()) && !display->isPoweredOn()) { return; } @@ -1967,6 +1974,7 @@ void SurfaceFlinger::rebuildLayerStacks() { mDrawingState.traverseInZOrder([&](Layer* layer) { bool hwcLayerDestroyed = false; + const auto displayId = display->getId(); if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); @@ -1976,13 +1984,13 @@ void SurfaceFlinger::rebuildLayerStacks() { } else { // Clear out the HWC layer if this layer was // previously visible, but no longer is - hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); + hwcLayerDestroyed = displayId && layer->destroyHwcLayer(*displayId); } } else { // WM changes display->layerStack upon sleep/awake. // Here we make sure we delete the HWC layers even if // WM changed their layer stack. - hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); + hwcLayerDestroyed = displayId && layer->destroyHwcLayer(*displayId); } // If a layer is not going to get a release fence because @@ -2107,12 +2115,11 @@ void SurfaceFlinger::beginFrame(const sp<DisplayDevice>& display) // emit any black frames until a layer is added to the layer stack. bool mustRecompose = dirty && !(empty && wasEmpty); - ALOGV_IF(display->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL, - "id[%d]: %s composition (%sdirty %sempty %swasEmpty)", display->getId(), - mustRecompose ? "doing" : "skipping", - dirty ? "+" : "-", - empty ? "+" : "-", - wasEmpty ? "+" : "-"); + const char flagPrefix[] = {'-', '+'}; + static_cast<void>(flagPrefix); + ALOGV_IF(display->isVirtual(), "%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", + __FUNCTION__, mustRecompose ? "doing" : "skipping", display->getDebugName().c_str(), + flagPrefix[dirty], flagPrefix[empty], flagPrefix[wasEmpty]); display->beginFrame(mustRecompose); @@ -2129,10 +2136,8 @@ void SurfaceFlinger::prepareFrame(const sp<DisplayDevice>& display) status_t result = display->prepareFrame(getHwComposer(), getBE().mCompositionInfo[display->getDisplayToken()]); - ALOGE_IF(result != NO_ERROR, - "prepareFrame for display %d failed:" - " %d (%s)", - display->getId(), result, strerror(-result)); + ALOGE_IF(result != NO_ERROR, "prepareFrame failed for %s: %d (%s)", + display->getDebugName().c_str(), result, strerror(-result)); } void SurfaceFlinger::doComposition(const sp<DisplayDevice>& display, bool repaintEverything) { @@ -2155,8 +2160,9 @@ void SurfaceFlinger::doComposition(const sp<DisplayDevice>& display, bool repain void SurfaceFlinger::postFrame() { // |mStateLock| not needed as we are on the main thread - if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) { - uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount(); + const auto display = getDefaultDisplayDeviceLocked(); + if (display && getHwComposer().isConnected(*display->getId())) { + uint32_t flipCount = display->getPageFlipCount(); if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { logFrameStats(); } @@ -2172,8 +2178,8 @@ void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& display) if (display->isPoweredOn()) { const auto displayId = display->getId(); - if (displayId >= 0) { - getBE().mHwc->presentAndGetReleaseFences(displayId); + if (displayId) { + getHwComposer().presentAndGetReleaseFences(*displayId); } display->onSwapBuffersCompleted(); display->makeCurrent(); @@ -2183,9 +2189,9 @@ void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& display) // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. - auto hwcLayer = layer->getHwcLayer(displayId); - if (displayId >= 0) { - releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer); + if (displayId && layer->hasHwcLayer(*displayId)) { + releaseFence = getHwComposer().getLayerReleaseFence(*displayId, + layer->getHwcLayer(*displayId)); } // If the layer was client composited in the previous frame, we @@ -2205,14 +2211,15 @@ void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& display) // display->getVisibleLayersSortedByZ. The best we can do is to // supply them with the present fence. if (!display->getLayersNeedingFences().isEmpty()) { - sp<Fence> presentFence = getBE().mHwc->getPresentFence(displayId); + sp<Fence> presentFence = + displayId ? getBE().mHwc->getPresentFence(*displayId) : Fence::NO_FENCE; for (auto& layer : display->getLayersNeedingFences()) { layer->getBE().onLayerDisplayed(presentFence); } } - if (displayId >= 0) { - getBE().mHwc->clearReleaseFences(displayId); + if (displayId) { + getHwComposer().clearReleaseFences(*displayId); } } } @@ -2247,72 +2254,36 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // here the transaction has been committed } -DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t hwcDisplayId, - HWC2::Connection connection) const { - // Figure out whether the event is for the primary display or an - // external display by matching the Hwc display id against one for a - // connected display. If we did not find a match, we then check what - // displays are not already connected to determine the type. If we don't - // have a connected primary display, we assume the new display is meant to - // be the primary display, and then if we don't have an external display, - // we assume it is that. - const auto primaryHwcDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY); - const auto externalHwcDisplayId = - getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL); - if (primaryHwcDisplayId && primaryHwcDisplayId == hwcDisplayId) { - return DisplayDevice::DISPLAY_PRIMARY; - } else if (externalHwcDisplayId && externalHwcDisplayId == hwcDisplayId) { - return DisplayDevice::DISPLAY_EXTERNAL; - } else if (connection == HWC2::Connection::Connected && !primaryHwcDisplayId) { - return DisplayDevice::DISPLAY_PRIMARY; - } else if (connection == HWC2::Connection::Connected && !externalHwcDisplayId) { - return DisplayDevice::DISPLAY_EXTERNAL; - } - - return DisplayDevice::DISPLAY_ID_INVALID; -} - void SurfaceFlinger::processDisplayHotplugEventsLocked() { for (const auto& event : mPendingHotplugEvents) { - auto displayType = determineDisplayType(event.hwcDisplayId, event.connection); - if (displayType == DisplayDevice::DISPLAY_ID_INVALID) { - ALOGW("Unable to determine the display type for display %" PRIu64, event.hwcDisplayId); - continue; - } + const std::optional<DisplayIdentificationInfo> info = + getHwComposer().onHotplug(event.hwcDisplayId, event.connection); - if (getBE().mHwc->isUsingVrComposer() && displayType == DisplayDevice::DISPLAY_EXTERNAL) { - ALOGE("External displays are not supported by the vr hardware composer."); + if (!info) { continue; } - const auto displayId = - getBE().mHwc->onHotplug(event.hwcDisplayId, displayType, event.connection); - if (displayId) { - ALOGV("Display %" PRIu64 " has stable ID %" PRIu64, event.hwcDisplayId, *displayId); - } - if (event.connection == HWC2::Connection::Connected) { - if (!mDisplayTokens[displayType].get()) { - ALOGV("Creating built in display %d", displayType); - mDisplayTokens[displayType] = new BBinder(); - DisplayDeviceState info; - info.type = displayType; - info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? - "Built-in Screen" : "External Screen"; - info.isSecure = true; // All physical displays are currently considered secure. - mCurrentState.displays.add(mDisplayTokens[displayType], info); - mInterceptor->saveDisplayCreation(info); + if (!mPhysicalDisplayTokens.count(info->id)) { + ALOGV("Creating display %" PRIu64, info->id); + mPhysicalDisplayTokens[info->id] = new BBinder(); + DisplayDeviceState state; + state.displayId = info->id; + state.isSecure = true; // All physical displays are currently considered secure. + state.displayName = info->name; + mCurrentState.displays.add(mPhysicalDisplayTokens[info->id], state); + mInterceptor->saveDisplayCreation(state); } } else { - ALOGV("Removing built in display %d", displayType); + ALOGV("Removing display %" PRIu64, info->id); - ssize_t idx = mCurrentState.displays.indexOfKey(mDisplayTokens[displayType]); - if (idx >= 0) { - const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); - mInterceptor->saveDisplayDeletion(info.sequenceId); - mCurrentState.displays.removeItemsAt(idx); + ssize_t index = mCurrentState.displays.indexOfKey(mPhysicalDisplayTokens[info->id]); + if (index >= 0) { + const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); + mInterceptor->saveDisplayDeletion(state.sequenceId); + mCurrentState.displays.removeItemsAt(index); } - mDisplayTokens[displayType].clear(); + mPhysicalDisplayTokens.erase(info->id); } processDisplayChangesLocked(); @@ -2322,31 +2293,36 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( - const wp<IBinder>& displayToken, int32_t displayId, const DisplayDeviceState& state, - const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { - DisplayDeviceCreationArgs creationArgs(this, displayToken, state.type, displayId); + const wp<IBinder>& displayToken, const std::optional<DisplayId>& displayId, + const DisplayDeviceState& state, const sp<DisplaySurface>& dispSurface, + const sp<IGraphicBufferProducer>& producer) { + DisplayDeviceCreationArgs creationArgs(this, displayToken, displayId); + creationArgs.isVirtual = state.isVirtual(); creationArgs.isSecure = state.isSecure; creationArgs.displaySurface = dispSurface; creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; - if (useColorManagement && displayId >= 0) { - std::vector<ColorMode> modes = getHwComposer().getColorModes(displayId); + const bool isInternalDisplay = displayId && displayId == getInternalDisplayId(); + creationArgs.isPrimary = isInternalDisplay; + + if (useColorManagement && displayId) { + std::vector<ColorMode> modes = getHwComposer().getColorModes(*displayId); for (ColorMode colorMode : modes) { if (isWideColorMode(colorMode)) { creationArgs.hasWideColorGamut = true; } std::vector<RenderIntent> renderIntents = - getHwComposer().getRenderIntents(displayId, colorMode); + getHwComposer().getRenderIntents(*displayId, colorMode); creationArgs.hwcColorModes.emplace(colorMode, renderIntents); } } - if (displayId >= 0) { - getHwComposer().getHdrCapabilities(displayId, &creationArgs.hdrCapabilities); + if (displayId) { + getHwComposer().getHdrCapabilities(*displayId, &creationArgs.hdrCapabilities); creationArgs.supportedPerFrameMetadata = - getHwComposer().getSupportedPerFrameMetadata(displayId); + getHwComposer().getSupportedPerFrameMetadata(*displayId); } auto nativeWindowSurface = getFactory().createNativeWindowSurface(producer); @@ -2357,7 +2333,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( * Create our display's surface */ std::unique_ptr<renderengine::Surface> renderSurface = getRenderEngine().createSurface(); - renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY); + renderSurface->setCritical(isInternalDisplay); renderSurface->setAsync(state.isVirtual()); renderSurface->setNativeWindow(nativeWindow.get()); creationArgs.displayWidth = renderSurface->getWidth(); @@ -2375,9 +2351,8 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( nativeWindow->setSwapInterval(nativeWindow.get(), 0); } - creationArgs.displayInstallOrientation = state.type == DisplayDevice::DISPLAY_PRIMARY - ? primaryDisplayOrientation - : DisplayState::eOrientationDefault; + creationArgs.displayInstallOrientation = + isInternalDisplay ? primaryDisplayOrientation : DisplayState::eOrientationDefault; // virtual displays are always considered enabled creationArgs.initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; @@ -2396,9 +2371,11 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( } setActiveColorModeInternal(display, defaultColorMode, defaultDataSpace, RenderIntent::COLORIMETRIC); - if (state.type < DisplayDevice::DISPLAY_VIRTUAL) { - display->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type)); + if (!state.isVirtual()) { + LOG_ALWAYS_FATAL_IF(!displayId); + display->setActiveConfig(getHwComposer().getActiveConfigIndex(*displayId)); } + display->setLayerStack(state.layerStack); display->setProjection(state.orientation, state.viewport, state.frame); display->setDisplayName(state.displayName); @@ -2424,6 +2401,10 @@ void SurfaceFlinger::processDisplayChangesLocked() { for (size_t i = 0; i < dc;) { const ssize_t j = curr.indexOfKey(draw.keyAt(i)); if (j < 0) { + // Save display IDs before disconnecting. + const auto internalDisplayId = getInternalDisplayId(); + const auto externalDisplayId = getExternalDisplayId(); + // in drawing state but not in current state // Call makeCurrent() on the primary display so we can // be sure that nothing associated with this display @@ -2434,14 +2415,14 @@ void SurfaceFlinger::processDisplayChangesLocked() { if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) { display->disconnect(getHwComposer()); } - if (draw[i].type == DisplayDevice::DISPLAY_PRIMARY) { + if (internalDisplayId && internalDisplayId == draw[i].displayId) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::Primary, false); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false); } - } else if (draw[i].type == DisplayDevice::DISPLAY_EXTERNAL) { + } else if (externalDisplayId && externalDisplayId == draw[i].displayId) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::External, false); @@ -2499,14 +2480,14 @@ void SurfaceFlinger::processDisplayChangesLocked() { sp<IGraphicBufferConsumer> bqConsumer; getFactory().createBufferQueue(&bqProducer, &bqConsumer, false); - int32_t displayId = -1; + std::optional<DisplayId> displayId; if (state.isVirtual()) { // Virtual displays without a surface are dormant: // they have external state (layer stack, projection, // etc.) but no internal state (i.e. a DisplayDevice). if (state.surface != nullptr) { // Allow VR composer to use virtual displays. - if (mUseHwcVirtualDisplays || getBE().mHwc->isUsingVrComposer()) { + if (mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()) { int width = 0; int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width); ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status); @@ -2518,14 +2499,14 @@ void SurfaceFlinger::processDisplayChangesLocked() { ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status); auto format = static_cast<ui::PixelFormat>(intFormat); - getBE().mHwc->allocateVirtualDisplay(width, height, &format, - &displayId); + displayId = + getHwComposer().allocateVirtualDisplay(width, height, &format); } // TODO: Plumb requested format back up to consumer sp<VirtualDisplaySurface> vds = - new VirtualDisplaySurface(*getBE().mHwc, displayId, state.surface, + new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, bqProducer, bqConsumer, state.displayName); @@ -2538,8 +2519,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { "surface is provided (%p), ignoring it", state.surface.get()); - displayId = state.type; - dispSurface = new FramebufferSurface(*getBE().mHwc, displayId, bqConsumer); + displayId = state.displayId; + LOG_ALWAYS_FATAL_IF(!displayId); + dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer); producer = bqProducer; } @@ -2549,7 +2531,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { setupNewDisplayDeviceInternal(displayToken, displayId, state, dispSurface, producer)); if (!state.isVirtual()) { - if (state.type == DisplayDevice::DISPLAY_PRIMARY) { + LOG_ALWAYS_FATAL_IF(!displayId); + + if (displayId == getInternalDisplayId()) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::Primary, @@ -2558,7 +2542,7 @@ void SurfaceFlinger::processDisplayChangesLocked() { mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, true); } - } else if (state.type == DisplayDevice::DISPLAY_EXTERNAL) { + } else if (displayId == getExternalDisplayId()) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::External, @@ -2712,7 +2696,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) void SurfaceFlinger::updateCursorAsync() { for (const auto& [token, display] : mDisplays) { - if (display->getId() < 0) { + if (!display->getId()) { continue; } @@ -3104,8 +3088,9 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& display) { case HWC2::Composition::Device: case HWC2::Composition::Sideband: case HWC2::Composition::SolidColor: { + LOG_ALWAYS_FATAL_IF(!displayId); const Layer::State& state(layer->getDrawingState()); - if (layer->getClearClientTarget(displayId) && !firstLayer && + if (layer->getClearClientTarget(*displayId) && !firstLayer && layer->isOpaque(state) && (layer->getAlpha() == 1.0f) && hasClientComposition) { // never clear the very first layer since we're @@ -3806,7 +3791,7 @@ void SurfaceFlinger::onHandleDestroyed(const sp<Layer>& layer) // --------------------------------------------------------------------------- void SurfaceFlinger::onInitializeDisplays() { - const auto displayToken = mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]; + const auto displayToken = getInternalDisplayToken(); if (!displayToken) return; // reset screen orientation and use primary layer stack @@ -3830,7 +3815,7 @@ void SurfaceFlinger::onInitializeDisplays() { setPowerModeInternal(display, HWC_POWER_MODE_NORMAL, /*stateLockHeld*/ false); - const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); + const auto activeConfig = getHwComposer().getActiveConfig(*display->getId()); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); @@ -3847,16 +3832,18 @@ void SurfaceFlinger::initializeDisplays() { void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode, bool stateLockHeld) { - const int32_t displayId = display->getId(); - ALOGD("Setting power mode %d on display %d", mode, displayId); - - int currentMode = display->getPowerMode(); - if (mode == currentMode) { + if (display->isVirtual()) { + ALOGE("%s: Invalid operation on virtual display", __FUNCTION__); return; } - if (display->isVirtual()) { - ALOGW("Trying to set power mode for virtual display"); + const auto displayId = display->getId(); + LOG_ALWAYS_FATAL_IF(!displayId); + + ALOGD("Setting power mode %d on display %" PRIu64, mode, *displayId); + + int currentMode = display->getPowerMode(); + if (mode == currentMode) { return; } @@ -3872,12 +3859,10 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).sequenceId, mode); } - int32_t type = display->getDisplayType(); if (currentMode == HWC_POWER_MODE_OFF) { // Turn on the display - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) { - // FIXME: eventthread only knows about the main display right now if (mUseScheduler) { mScheduler->onScreenAcquired(mAppConnectionHandle); } else { @@ -3908,7 +3893,6 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int } else { disableHardwareVsync(true); // also cancels any in-progress resync } - // FIXME: eventthread only knows about the main display right now if (mUseScheduler) { mScheduler->onScreenReleased(mAppConnectionHandle); } else { @@ -3916,15 +3900,14 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int } } - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); mVisibleRegionsDirty = true; // from this point on, SF will stop drawing on this display } else if (mode == HWC_POWER_MODE_DOZE || mode == HWC_POWER_MODE_NORMAL) { // Update display while dozing - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); if (display->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) { - // FIXME: eventthread only knows about the main display right now if (mUseScheduler) { mScheduler->onScreenAcquired(mAppConnectionHandle); } else { @@ -3940,24 +3923,23 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int } else { disableHardwareVsync(true); // also cancels any in-progress resync } - // FIXME: eventthread only knows about the main display right now if (mUseScheduler) { mScheduler->onScreenReleased(mAppConnectionHandle); } else { mEventThread->onScreenReleased(); } } - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); } else { ALOGE("Attempting to set unknown power mode: %d\n", mode); - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); } if (display->isPrimary()) { mTimeStats.setPowerMode(mode); } - ALOGD("Finished setting power mode %d on display %d", mode, displayId); + ALOGD("Finished setting power mode %d on display %" PRIu64, mode, *displayId); } void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { @@ -4136,9 +4118,9 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index index++; } - if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY; - getHwComposer().isConnected(displayId)) { - const auto activeConfig = getBE().mHwc->getActiveConfig(displayId); + if (const auto displayId = getInternalDisplayId(); + displayId && getHwComposer().isConnected(*displayId)) { + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); const nsecs_t period = activeConfig->getVsyncPeriod(); result.appendFormat("%" PRId64 "\n", period); } @@ -4279,13 +4261,17 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const { for (const auto& [token, display] : mDisplays) { - const int32_t displayId = display->getId(); - const auto hwcDisplayId = getHwComposer().getHwcDisplayId(displayId); + const auto displayId = display->getId(); + if (!displayId) { + continue; + } + const auto hwcDisplayId = getHwComposer().fromPhysicalDisplayId(*displayId); if (!hwcDisplayId) { continue; } - result.appendFormat("Display %d (HWC display %" PRIu64 "): ", displayId, *hwcDisplayId); + result.appendFormat("Display %" PRIu64 " (HWC display %" PRIu64 "): ", *displayId, + *hwcDisplayId); uint8_t port; DisplayIdentificationData data; if (!getHwComposer().getDisplayIdentificationData(*hwcDisplayId, &port, &data)) { @@ -4316,7 +4302,6 @@ void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const { result.append(edid->displayName.data(), edid->displayName.length()); result.append("\"\n"); } - result.append("\n"); } void SurfaceFlinger::dumpWideColorInfo(String8& result) const { @@ -4328,13 +4313,13 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { // TODO: print out if wide-color mode is active or not for (const auto& [token, display] : mDisplays) { - const int32_t displayId = display->getId(); - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + const auto displayId = display->getId(); + if (!displayId) { continue; } - result.appendFormat("Display %d color modes:\n", displayId); - std::vector<ColorMode> modes = getHwComposer().getColorModes(displayId); + result.appendFormat("Display %" PRIu64 " color modes:\n", *displayId); + std::vector<ColorMode> modes = getHwComposer().getColorModes(*displayId); for (auto&& mode : modes) { result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode); } @@ -4390,11 +4375,12 @@ LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& disp layersProto.set_color_transform(decodeColorTransform(display.getColorTransform())); layersProto.set_global_transform(static_cast<int32_t>(display.getOrientationTransform())); - const int32_t displayId = display.getId(); + const auto displayId = display.getId(); + LOG_ALWAYS_FATAL_IF(!displayId); mDrawingState.traverseInZOrder([&](Layer* layer) { - if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(displayId)) { + if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(*displayId)) { LayerProto* layerProto = layersProto.add_layers(); - layer->writeToProto(layerProto, displayId); + layer->writeToProto(layerProto, *displayId); } }); @@ -4448,25 +4434,19 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets(); const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets(); - if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY; - getHwComposer().isConnected(displayId)) { - const auto activeConfig = getHwComposer().getActiveConfig(displayId); - result.appendFormat("Display %d: " - "app phase %" PRId64 " ns, " - "sf phase %" PRId64 " ns, " - "early app phase %" PRId64 " ns, " - "early sf phase %" PRId64 " ns, " - "early app gl phase %" PRId64 " ns, " - "early sf gl phase %" PRId64 " ns, " - "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", - displayId, - vsyncPhaseOffsetNs, - sfVsyncPhaseOffsetNs, - appEarlyOffset, - sfEarlyOffset, - appEarlyGlOffset, - sfEarlyGlOffset, - dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); + if (const auto displayId = getInternalDisplayId(); + displayId && getHwComposer().isConnected(*displayId)) { + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); + result.appendFormat("Display %" PRIu64 ": app phase %" PRId64 " ns, " + "sf phase %" PRId64 " ns, " + "early app phase %" PRId64 " ns, " + "early sf phase %" PRId64 " ns, " + "early app gl phase %" PRId64 " ns, " + "early sf gl phase %" PRId64 " ns, " + "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", + *displayId, vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset, + sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset, + dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); } result.append("\n"); @@ -4519,12 +4499,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, result.append("SurfaceFlinger global state:\n"); colorizer.reset(result); - HWComposer& hwc(getHwComposer()); - const auto display = getDefaultDisplayDeviceLocked(); - getBE().mRenderEngine->dump(result); - if (display) { + if (const auto display = getDefaultDisplayDeviceLocked()) { display->undefinedRegion.dump(result, "undefinedRegion"); result.appendFormat(" orientation=%d, isPoweredOn=%d\n", display->getOrientation(), display->isPoweredOn()); @@ -4533,8 +4510,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, " gpu_to_cpu_unsupported : %d\n", mTransactionFlags.load(), !mGpuToCpuSupported); - if (display) { - const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); + if (const auto displayId = getInternalDisplayId(); + displayId && getHwComposer().isConnected(*displayId)) { + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); result.appendFormat(" refresh-rate : %f fps\n" " x-dpi : %f\n" " y-dpi : %f\n", @@ -4566,14 +4544,14 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, * HWC layer minidump */ for (const auto& [token, display] : mDisplays) { - const int32_t displayId = display->getId(); - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + const auto displayId = display->getId(); + if (!displayId) { continue; } - result.appendFormat("Display %d HWC layers:\n", displayId); + result.appendFormat("Display %" PRIu64 " HWC layers:\n", *displayId); Layer::miniDumpHeader(result); - mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, displayId); }); + mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, *displayId); }); result.append("\n"); } @@ -4586,7 +4564,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, bool hwcDisabled = mDebugDisableHWC || mDebugRegion; result.appendFormat(" h/w composer %s\n", hwcDisabled ? "disabled" : "enabled"); - hwc.dump(result); + getHwComposer().dump(result); /* * Dump gralloc state @@ -4604,7 +4582,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, } } -const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int32_t displayId) { +const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayId displayId) { // Note: mStateLock is held here for (const auto& [token, display] : mDisplays) { if (display->getId() == displayId) { @@ -4612,7 +4590,7 @@ const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int32_t } } - ALOGE("%s: Invalid display %d", __FUNCTION__, displayId); + ALOGE("%s: Invalid display %" PRIu64, __FUNCTION__, displayId); static const Vector<sp<Layer>> empty; return empty; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 51168a672..36bb62c08 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -76,10 +76,11 @@ #include <map> #include <mutex> #include <queue> +#include <set> #include <string> #include <thread> +#include <unordered_map> #include <utility> -#include "RenderArea.h" #include <layerproto/LayerProtoHeader.h> @@ -348,7 +349,7 @@ public: // enable/disable h/w composer event // TODO: this should be made accessible only to EventThread - void setVsyncEnabled(int disp, int enabled); + void setVsyncEnabled(EventThread::DisplayType displayType, bool enabled); // called on the main thread by MessageQueue when an internal message // is received @@ -357,7 +358,7 @@ public: // for debugging only // TODO: this should be made accessible only to HWComposer - const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id); + const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId); renderengine::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; } @@ -659,7 +660,10 @@ private: } sp<DisplayDevice> getDefaultDisplayDeviceLocked() { - return getDisplayDeviceLocked(mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]); + if (const auto token = getInternalDisplayToken()) { + return getDisplayDeviceLocked(token); + } + return nullptr; } // mark a region of a layer stack dirty. this updates the dirty @@ -724,10 +728,8 @@ private: /* ------------------------------------------------------------------------ * Display management */ - DisplayDevice::DisplayType determineDisplayType(hwc2_display_t hwcDisplayId, - HWC2::Connection connection) const; sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken, - int32_t displayId, + const std::optional<DisplayId>& displayId, const DisplayDeviceState& state, const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer); @@ -759,6 +761,37 @@ public: } private: + sp<IBinder> getPhysicalDisplayToken(DisplayId displayId) const { + const auto it = mPhysicalDisplayTokens.find(displayId); + return it != mPhysicalDisplayTokens.end() ? it->second : nullptr; + } + + std::optional<DisplayId> getPhysicalDisplayId(const sp<IBinder>& displayToken) const { + for (const auto& [id, token] : mPhysicalDisplayTokens) { + if (token == displayToken) { + return id; + } + } + return {}; + } + + // TODO(b/74619554): Remove special cases for primary display. + sp<IBinder> getInternalDisplayToken() const { + const auto displayId = getInternalDisplayId(); + return displayId ? getPhysicalDisplayToken(*displayId) : nullptr; + } + + std::optional<DisplayId> getInternalDisplayId() const { + const auto hwcDisplayId = getHwComposer().getInternalHwcDisplayId(); + return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt; + } + + // TODO(b/74619554): Remove special cases for external display. + std::optional<DisplayId> getExternalDisplayId() const { + const auto hwcDisplayId = getHwComposer().getExternalHwcDisplayId(); + return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt; + } + void listLayersLocked(const Vector<String16>& args, size_t& index, String8& result) const; void dumpStatsLocked(const Vector<String16>& args, size_t& index, String8& result) const; void clearStatsLocked(const Vector<String16>& args, size_t& index, String8& result); @@ -836,7 +869,7 @@ private: std::unique_ptr<VSyncSource> mSfEventThreadSource; std::unique_ptr<InjectVSyncSource> mVSyncInjector; std::unique_ptr<EventControlThread> mEventControlThread; - sp<IBinder> mDisplayTokens[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; + std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens; VSyncModulator mVsyncModulator; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 57bda5a8c..7faaff6ea 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -495,8 +495,10 @@ void SurfaceInterceptor::addDisplayCreationLocked(Increment* increment, DisplayCreation* creation(increment->mutable_display_creation()); creation->set_id(info.sequenceId); creation->set_name(info.displayName); - creation->set_type(info.type); creation->set_is_secure(info.isSecure); + if (info.displayId) { + creation->set_display_id(*info.displayId); + } } void SurfaceInterceptor::addDisplayDeletionLocked(Increment* increment, int32_t sequenceId) { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index f1a8842b1..09bb8c58f 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -65,6 +65,7 @@ constexpr hwc2_display_t HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPL constexpr hwc2_layer_t HWC_LAYER = 5000; constexpr Transform DEFAULT_TRANSFORM = static_cast<Transform>(0); +constexpr DisplayId DEFAULT_DISPLAY_ID = 42; constexpr int DEFAULT_DISPLAY_WIDTH = 1920; constexpr int DEFAULT_DISPLAY_HEIGHT = 1024; @@ -226,12 +227,13 @@ struct BaseDisplayVariant { static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL; static void setupPreconditions(CompositionTest* test) { - FakeHwcDisplayInjector(DisplayDevice::DISPLAY_PRIMARY, HWC2::DisplayType::Physical) + FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, HWC2::DisplayType::Physical, + true /* isPrimary */) .setCapabilities(&test->mDefaultCapabilities) .inject(&test->mFlinger, test->mComposer); - test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DisplayDevice::DISPLAY_PRIMARY, - DisplayDevice::DISPLAY_PRIMARY) + test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID, + false /* isVirtual */, true /* isPrimary */) .setDisplaySize(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT) .setDisplaySurface(test->mDisplaySurface) .setRenderSurface(std::unique_ptr<renderengine::Surface>( @@ -745,7 +747,9 @@ struct BaseLayerVariant { EXPECT_CALL(*test->mComposer, createLayer(HWC_DISPLAY, _)) .WillOnce(DoAll(SetArgPointee<1>(HWC_LAYER), Return(Error::NONE))); - layer->createHwcLayer(test->mFlinger.mFlinger->getBE().mHwc.get(), test->mDisplay->getId()); + const auto displayId = test->mDisplay->getId(); + ASSERT_TRUE(displayId); + layer->createHwcLayer(test->mFlinger.mFlinger->getBE().mHwc.get(), *displayId); Mock::VerifyAndClear(test->mComposer); @@ -758,8 +762,10 @@ struct BaseLayerVariant { static void cleanupInjectedLayers(CompositionTest* test) { EXPECT_CALL(*test->mComposer, destroyLayer(HWC_DISPLAY, HWC_LAYER)) .WillOnce(Return(Error::NONE)); + const auto displayId = test->mDisplay->getId(); + ASSERT_TRUE(displayId); for (auto layer : test->mFlinger.mutableDrawingState().layersSortedByZ) { - layer->destroyHwcLayer(test->mDisplay->getId()); + layer->destroyHwcLayer(*displayId); } test->mFlinger.mutableDrawingState().layersSortedByZ.clear(); } @@ -947,7 +953,7 @@ struct RECompositionResultVariant : public CompositionResultBaseVariant { struct ForcedClientCompositionResultVariant : public RECompositionResultVariant { static void setupLayerState(CompositionTest*, sp<Layer> layer) { - layer->forceClientComposition(DisplayDevice::DISPLAY_PRIMARY); + layer->forceClientComposition(DEFAULT_DISPLAY_ID); } template <typename Case> diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp index 4f1c99e41..55995d048 100644 --- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp @@ -68,32 +68,44 @@ DisplayIdentificationData asDisplayIdentificationData(const unsigned char (&byte } // namespace +const DisplayIdentificationData& getInternalEdid() { + static const DisplayIdentificationData data = asDisplayIdentificationData(kInternalEdid); + return data; +} + +const DisplayIdentificationData& getExternalEdid() { + static const DisplayIdentificationData data = asDisplayIdentificationData(kExternalEdid); + return data; +} + +const DisplayIdentificationData& getExternalEedid() { + static const DisplayIdentificationData data = asDisplayIdentificationData(kExternalEedid); + return data; +} + TEST(DisplayIdentificationTest, isEdid) { EXPECT_FALSE(isEdid({})); - EXPECT_TRUE(isEdid(asDisplayIdentificationData(kInternalEdid))); - EXPECT_TRUE(isEdid(asDisplayIdentificationData(kExternalEdid))); - EXPECT_TRUE(isEdid(asDisplayIdentificationData(kExternalEedid))); + EXPECT_TRUE(isEdid(getInternalEdid())); + EXPECT_TRUE(isEdid(getExternalEdid())); + EXPECT_TRUE(isEdid(getExternalEedid())); } TEST(DisplayIdentificationTest, parseEdid) { - auto data = asDisplayIdentificationData(kInternalEdid); - auto edid = parseEdid(data); + auto edid = parseEdid(getInternalEdid()); ASSERT_TRUE(edid); EXPECT_EQ(0x4ca3u, edid->manufacturerId); EXPECT_STREQ("SEC", edid->pnpId.data()); // ASCII text should be used as fallback if display name and serial number are missing. EXPECT_EQ("121AT11-801", edid->displayName); - data = asDisplayIdentificationData(kExternalEdid); - edid = parseEdid(data); + edid = parseEdid(getExternalEdid()); ASSERT_TRUE(edid); EXPECT_EQ(0x22f0u, edid->manufacturerId); EXPECT_STREQ("HWP", edid->pnpId.data()); EXPECT_EQ("HP ZR30w", edid->displayName); - data = asDisplayIdentificationData(kExternalEedid); - edid = parseEdid(data); + edid = parseEdid(getExternalEedid()); ASSERT_TRUE(edid); EXPECT_EQ(0x4c2du, edid->manufacturerId); EXPECT_STREQ("SAM", edid->pnpId.data()); @@ -105,7 +117,7 @@ TEST(DisplayIdentificationTest, parseInvalidEdid) { EXPECT_FALSE(parseEdid({})); // Display name must be printable. - auto data = asDisplayIdentificationData(kExternalEdid); + auto data = getExternalEdid(); data[97] = '\x1b'; auto edid = parseEdid(data); ASSERT_TRUE(edid); @@ -128,20 +140,32 @@ TEST(DisplayIdentificationTest, getPnpId) { EXPECT_STREQ("SAM", getPnpId(0x4c2du).value_or(PnpId{}).data()); } -TEST(DisplayIdentificationTest, generateDisplayId) { - const auto primaryId = generateDisplayId(0, asDisplayIdentificationData(kInternalEdid)); - ASSERT_TRUE(primaryId); +TEST(DisplayIdentificationTest, parseDisplayIdentificationData) { + const auto primaryInfo = parseDisplayIdentificationData(0, getInternalEdid()); + ASSERT_TRUE(primaryInfo); - const auto secondaryId = generateDisplayId(1, asDisplayIdentificationData(kExternalEdid)); - ASSERT_TRUE(secondaryId); + const auto secondaryInfo = parseDisplayIdentificationData(1, getExternalEdid()); + ASSERT_TRUE(secondaryInfo); - const auto tertiaryId = generateDisplayId(2, asDisplayIdentificationData(kExternalEedid)); - ASSERT_TRUE(tertiaryId); + const auto tertiaryInfo = parseDisplayIdentificationData(2, getExternalEedid()); + ASSERT_TRUE(tertiaryInfo); // Display IDs should be unique. - EXPECT_NE(primaryId, secondaryId); - EXPECT_NE(primaryId, tertiaryId); - EXPECT_NE(secondaryId, tertiaryId); + EXPECT_NE(primaryInfo->id, secondaryInfo->id); + EXPECT_NE(primaryInfo->id, tertiaryInfo->id); + EXPECT_NE(secondaryInfo->id, tertiaryInfo->id); +} + +TEST(DisplayIdentificationTest, getFallbackDisplayId) { + // Manufacturer ID should be invalid. + ASSERT_FALSE(getPnpId(getFallbackDisplayId(0))); + ASSERT_FALSE(getPnpId(getFallbackDisplayId(0xffu))); +} + +TEST(DisplayIdentificationTest, getVirtualDisplayId) { + // Manufacturer ID should be invalid. + ASSERT_FALSE(getPnpId(getVirtualDisplayId(0))); + ASSERT_FALSE(getPnpId(getVirtualDisplayId(0xffff'ffffu))); } } // namespace android diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.h b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.h new file mode 100644 index 000000000..1c8e5cc9d --- /dev/null +++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.h @@ -0,0 +1,27 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "DisplayHardware/DisplayIdentification.h" + +namespace android { + +const DisplayIdentificationData& getInternalEdid(); +const DisplayIdentificationData& getExternalEdid(); +const DisplayIdentificationData& getExternalEedid(); + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index d32627a7d..2e90a5993 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -17,12 +17,16 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" +#include <type_traits> + #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include <ui/DebugUtils.h> + +#include "DisplayIdentificationTest.h" #include "TestableSurfaceFlinger.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/DisplayHardware/MockDisplaySurface.h" @@ -75,9 +79,11 @@ constexpr int HWC_POWER_MODE_LEET = 1337; // An out of range power mode value #define BOOL_SUBSTITUTE(TYPENAME) enum class TYPENAME : bool { FALSE = false, TRUE = true }; -BOOL_SUBSTITUTE(Critical); BOOL_SUBSTITUTE(Async); +BOOL_SUBSTITUTE(Critical); +BOOL_SUBSTITUTE(Primary); BOOL_SUBSTITUTE(Secure); +BOOL_SUBSTITUTE(Virtual); /* ------------------------------------------------------------------------ * @@ -98,7 +104,7 @@ public: // -------------------------------------------------------------------- // Postcondition helpers - bool hasHwcDisplay(hwc2_display_t displayId); + bool hasPhysicalHwcDisplay(hwc2_display_t hwcDisplayId); bool hasTransactionFlagSet(int flag); bool hasDisplayDevice(sp<IBinder> displayToken); sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken); @@ -204,8 +210,8 @@ void DisplayTransactionTest::injectFakeNativeWindowSurfaceFactory() { }); } -bool DisplayTransactionTest::hasHwcDisplay(hwc2_display_t displayId) { - return mFlinger.mutableHwcDisplaySlots().count(displayId) == 1; +bool DisplayTransactionTest::hasPhysicalHwcDisplay(hwc2_display_t hwcDisplayId) { + return mFlinger.mutableHwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1; } bool DisplayTransactionTest::hasTransactionFlagSet(int flag) { @@ -240,20 +246,67 @@ const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp<IBin * */ -template <DisplayDevice::DisplayType type, DisplayDevice::DisplayType displayId, int width, - int height, Critical critical, Async async, Secure secure, int grallocUsage> +template <typename PhysicalDisplay> +struct PhysicalDisplayId {}; + +template <DisplayId displayId> +using VirtualDisplayId = std::integral_constant<DisplayId, displayId>; + +struct NoDisplayId {}; + +template <typename> +struct IsPhysicalDisplayId : std::bool_constant<false> {}; + +template <typename PhysicalDisplay> +struct IsPhysicalDisplayId<PhysicalDisplayId<PhysicalDisplay>> : std::bool_constant<true> {}; + +template <typename> +struct DisplayIdGetter; + +template <typename PhysicalDisplay> +struct DisplayIdGetter<PhysicalDisplayId<PhysicalDisplay>> { + static std::optional<DisplayId> get() { + if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) { + return getFallbackDisplayId(static_cast<bool>(PhysicalDisplay::PRIMARY) + ? HWC_DISPLAY_PRIMARY + : HWC_DISPLAY_EXTERNAL); + } + + const auto info = + parseDisplayIdentificationData(PhysicalDisplay::PORT, + PhysicalDisplay::GET_IDENTIFICATION_DATA()); + return info ? std::make_optional(info->id) : std::nullopt; + } +}; + +template <DisplayId displayId> +struct DisplayIdGetter<VirtualDisplayId<displayId>> { + static std::optional<DisplayId> get() { return displayId; } +}; + +template <> +struct DisplayIdGetter<NoDisplayId> { + static std::optional<DisplayId> get() { return {}; } +}; + +// DisplayIdType can be: +// 1) PhysicalDisplayId<...> for generated ID of physical display backed by HWC. +// 2) VirtualDisplayId<...> for hard-coded ID of virtual display backed by HWC. +// 3) NoDisplayId for virtual display without HWC backing. +template <typename DisplayIdType, int width, int height, Critical critical, Async async, + Secure secure, Primary primary, int grallocUsage> struct DisplayVariant { + using DISPLAY_ID = DisplayIdGetter<DisplayIdType>; + // The display width and height static constexpr int WIDTH = width; static constexpr int HEIGHT = height; static constexpr int GRALLOC_USAGE = grallocUsage; - // The type for this display - static constexpr DisplayDevice::DisplayType TYPE = type; - static_assert(TYPE != DisplayDevice::DISPLAY_ID_INVALID); - - static constexpr DisplayDevice::DisplayType DISPLAY_ID = displayId; + // Whether the display is virtual or physical + static constexpr Virtual VIRTUAL = + IsPhysicalDisplayId<DisplayIdType>{} ? Virtual::FALSE : Virtual::TRUE; // When creating native window surfaces for the framebuffer, whether those should be critical static constexpr Critical CRITICAL = critical; @@ -264,8 +317,14 @@ struct DisplayVariant { // Whether the display should be treated as secure static constexpr Secure SECURE = secure; + // Whether the display is primary + static constexpr Primary PRIMARY = primary; + static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { - auto injector = FakeDisplayDeviceInjector(test->mFlinger, TYPE, DISPLAY_ID); + auto injector = + FakeDisplayDeviceInjector(test->mFlinger, DISPLAY_ID::get(), + static_cast<bool>(VIRTUAL), static_cast<bool>(PRIMARY)); + injector.setSecure(static_cast<bool>(SECURE)); return injector; } @@ -306,7 +365,8 @@ struct DisplayVariant { } }; -template <hwc2_display_t hwcDisplayId, HWC2::DisplayType hwcDisplayType, typename DisplayVariant> +template <hwc2_display_t hwcDisplayId, HWC2::DisplayType hwcDisplayType, typename DisplayVariant, + typename PhysicalDisplay = void> struct HwcDisplayVariant { // The display id supplied by the HWC static constexpr hwc2_display_t HWC_DISPLAY_ID = hwcDisplayId; @@ -325,7 +385,10 @@ struct HwcDisplayVariant { // Called by tests to inject a HWC display setup static void injectHwcDisplay(DisplayTransactionTest* test) { - FakeHwcDisplayInjector(DisplayVariant::TYPE, HWC_DISPLAY_TYPE) + const auto displayId = DisplayVariant::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + FakeHwcDisplayInjector(*displayId, HWC_DISPLAY_TYPE, + static_cast<bool>(DisplayVariant::PRIMARY)) .setHwcDisplayId(HWC_DISPLAY_ID) .setWidth(DisplayVariant::WIDTH) .setHeight(DisplayVariant::HEIGHT) @@ -362,8 +425,16 @@ struct HwcDisplayVariant { getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, IComposerClient::Attribute::DPI_Y, _)) .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE))); - EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) - .WillRepeatedly(Return(Error::UNSUPPORTED)); + + if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) { + EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) + .WillOnce(DoAll(SetArgPointee<1>(PhysicalDisplay::PORT), + SetArgPointee<2>(PhysicalDisplay::GET_IDENTIFICATION_DATA()), + Return(Error::NONE))); + } else { + EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) + .WillOnce(Return(Error::UNSUPPORTED)); + } } // Called by tests to set up HWC call expectations @@ -373,50 +444,67 @@ struct HwcDisplayVariant { } }; -struct NonHwcDisplayVariant { - static void injectHwcDisplay(DisplayTransactionTest*) {} - - static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0); - } -}; - // Physical displays are expected to be synchronous, secure, and have a HWC display for output. constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB; -template <hwc2_display_t hwcDisplayId, DisplayDevice::DisplayType type, int width, int height, +template <hwc2_display_t hwcDisplayId, typename PhysicalDisplay, int width, int height, Critical critical> struct PhysicalDisplayVariant - : public DisplayVariant<type, type, width, height, critical, Async::FALSE, Secure::TRUE, - GRALLOC_USAGE_PHYSICAL_DISPLAY>, - public HwcDisplayVariant<hwcDisplayId, HWC2::DisplayType::Physical, - DisplayVariant<type, type, width, height, critical, Async::FALSE, - Secure::TRUE, GRALLOC_USAGE_PHYSICAL_DISPLAY>> {}; + : DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height, critical, Async::FALSE, + Secure::TRUE, PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>, + HwcDisplayVariant<hwcDisplayId, HWC2::DisplayType::Physical, + DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height, + critical, Async::FALSE, Secure::TRUE, + PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>, + PhysicalDisplay> {}; + +template <bool hasIdentificationData> +struct PrimaryDisplay { + static constexpr Primary PRIMARY = Primary::TRUE; + static constexpr uint8_t PORT = 255; + static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData; + static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid; +}; + +template <bool hasIdentificationData> +struct ExternalDisplay { + static constexpr Primary PRIMARY = Primary::FALSE; + static constexpr uint8_t PORT = 254; + static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData; + static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid; +}; + +struct TertiaryDisplay { + static constexpr Primary PRIMARY = Primary::FALSE; +}; // A primary display is a physical display that is critical using PrimaryDisplayVariant = - PhysicalDisplayVariant<1001, DisplayDevice::DISPLAY_PRIMARY, 3840, 2160, Critical::TRUE>; + PhysicalDisplayVariant<1001, PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>; // An external display is physical display that is not critical. using ExternalDisplayVariant = - PhysicalDisplayVariant<1002, DisplayDevice::DISPLAY_EXTERNAL, 1920, 1280, Critical::FALSE>; + PhysicalDisplayVariant<1002, ExternalDisplay<false>, 1920, 1280, Critical::FALSE>; using TertiaryDisplayVariant = - PhysicalDisplayVariant<1003, DisplayDevice::DISPLAY_EXTERNAL, 1600, 1200, Critical::FALSE>; + PhysicalDisplayVariant<1003, TertiaryDisplay, 1600, 1200, Critical::FALSE>; // A virtual display not supported by the HWC. constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0; template <int width, int height, Secure secure> struct NonHwcVirtualDisplayVariant - : public DisplayVariant<DisplayDevice::DISPLAY_VIRTUAL, DisplayDevice::DISPLAY_ID_INVALID, - width, height, Critical::FALSE, Async::TRUE, secure, - GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY>, - public NonHwcDisplayVariant { - using Base = DisplayVariant<DisplayDevice::DISPLAY_VIRTUAL, DisplayDevice::DISPLAY_ID_INVALID, - width, height, Critical::FALSE, Async::TRUE, secure, - GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY>; + : DisplayVariant<NoDisplayId, width, height, Critical::FALSE, Async::TRUE, secure, + Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY> { + using Base = DisplayVariant<NoDisplayId, width, height, Critical::FALSE, Async::TRUE, secure, + Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY>; + + static void injectHwcDisplay(DisplayTransactionTest*) {} + + static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { + EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0); + } static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) { Base::setupNativeWindowSurfaceCreationCallExpectations(test); @@ -429,14 +517,14 @@ constexpr uint32_t GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY = GRALLOC_USAGE_HW_COMPOSER template <int width, int height, Secure secure> struct HwcVirtualDisplayVariant - : public DisplayVariant<DisplayDevice::DISPLAY_VIRTUAL, DisplayDevice::DISPLAY_VIRTUAL, width, - height, Critical::FALSE, Async::TRUE, secure, - GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>, - public HwcDisplayVariant<1010, HWC2::DisplayType::Virtual, - NonHwcVirtualDisplayVariant<width, height, secure>> { - using Base = - DisplayVariant<DisplayDevice::DISPLAY_VIRTUAL, DisplayDevice::DISPLAY_VIRTUAL, width, - height, Critical::FALSE, Async::TRUE, secure, GRALLOC_USAGE_HW_COMPOSER>; + : DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE, secure, + Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>, + HwcDisplayVariant< + 1010, HWC2::DisplayType::Virtual, + DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE, + secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> { + using Base = DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE, + secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER>; using Self = HwcVirtualDisplayVariant<width, height, secure>; static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) { @@ -850,8 +938,8 @@ TEST_F(DisplayTransactionTest, createDisplaySetsCurrentStateForNonsecureDisplay) // The display should have been added to the current state ASSERT_TRUE(hasCurrentDisplayState(displayToken)); const auto& display = getCurrentDisplayState(displayToken); - EXPECT_EQ(DisplayDevice::DISPLAY_VIRTUAL, display.type); - EXPECT_EQ(false, display.isSecure); + EXPECT_TRUE(display.isVirtual()); + EXPECT_FALSE(display.isSecure); EXPECT_EQ(name.string(), display.displayName); // -------------------------------------------------------------------- @@ -881,8 +969,8 @@ TEST_F(DisplayTransactionTest, createDisplaySetsCurrentStateForSecureDisplay) { // The display should have been added to the current state ASSERT_TRUE(hasCurrentDisplayState(displayToken)); const auto& display = getCurrentDisplayState(displayToken); - EXPECT_EQ(DisplayDevice::DISPLAY_VIRTUAL, display.type); - EXPECT_EQ(true, display.isSecure); + EXPECT_TRUE(display.isVirtual()); + EXPECT_TRUE(display.isSecure); EXPECT_EQ(name.string(), display.displayName); // -------------------------------------------------------------------- @@ -1002,9 +1090,12 @@ TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { */ class GetBestColorModeTest : public DisplayTransactionTest { public: + static constexpr DisplayId DEFAULT_DISPLAY_ID = 777; + GetBestColorModeTest() : DisplayTransactionTest(), - mInjector(FakeDisplayDeviceInjector(mFlinger, DisplayDevice::DISPLAY_PRIMARY, 0)) {} + mInjector(FakeDisplayDeviceInjector(mFlinger, DEFAULT_DISPLAY_ID, false /* isVirtual */, + true /* isPrimary */)) {} void setHasWideColorGamut(bool hasWideColorGamut) { mHasWideColorGamut = hasWideColorGamut; } @@ -1127,18 +1218,22 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { // Invocation DisplayDeviceState state; - state.type = Case::Display::TYPE; + state.displayId = static_cast<bool>(Case::Display::VIRTUAL) ? std::nullopt + : Case::Display::DISPLAY_ID::get(); state.isSecure = static_cast<bool>(Case::Display::SECURE); - auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, Case::Display::TYPE, state, - displaySurface, producer); + auto device = + mFlinger.setupNewDisplayDeviceInternal(displayToken, Case::Display::DISPLAY_ID::get(), + state, displaySurface, producer); // -------------------------------------------------------------------- // Postconditions ASSERT_TRUE(device != nullptr); - EXPECT_EQ(Case::Display::TYPE, device->getDisplayType()); + EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId()); + EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual()); EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure()); + EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary()); EXPECT_EQ(Case::Display::WIDTH, device->getWidth()); EXPECT_EQ(Case::Display::HEIGHT, device->getHeight()); EXPECT_EQ(Case::WideColorSupport::WIDE_COLOR_SUPPORTED, device->hasWideColorGamut()); @@ -1166,11 +1261,14 @@ TEST_F(SetupNewDisplayDeviceInternalTest, createNonHwcVirtualDisplay) { } TEST_F(SetupNewDisplayDeviceInternalTest, createHwcVirtualDisplay) { - // We need to resize this so that the HWC thinks the virtual display - // is something it created. - mFlinger.mutableHwcDisplayData().resize(3); + using Case = HwcVirtualDisplayCase; - setupNewDisplayDeviceInternalTest<HwcVirtualDisplayCase>(); + // Insert display data so that the HWC thinks it created the virtual display. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + mFlinger.mutableHwcDisplayData()[*displayId] = {}; + + setupNewDisplayDeviceInternalTest<Case>(); } TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3Display) { @@ -1258,7 +1356,7 @@ void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessin EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1); EXPECT_CALL(*mEventThread, - onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY + onHotplugReceived(static_cast<bool>(Case::Display::PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External, true)) @@ -1269,7 +1367,7 @@ template <typename Case> void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() { EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1); EXPECT_CALL(*mEventThread, - onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY + onHotplugReceived(static_cast<bool>(Case::Display::PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External, false)) @@ -1282,30 +1380,35 @@ void HandleTransactionLockedTest::verifyDisplayIsConnected(const sp<IBinder>& di ASSERT_TRUE(hasDisplayDevice(displayToken)); const auto& device = getDisplayDevice(displayToken); EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure()); - EXPECT_EQ(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY, device->isPrimary()); + EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary()); // The display should have been set up in the current display state ASSERT_TRUE(hasCurrentDisplayState(displayToken)); const auto& current = getCurrentDisplayState(displayToken); - EXPECT_EQ(Case::Display::TYPE, current.type); + EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), current.isVirtual()); + EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL) ? std::nullopt + : Case::Display::DISPLAY_ID::get(), + current.displayId); // The display should have been set up in the drawing display state ASSERT_TRUE(hasDrawingDisplayState(displayToken)); const auto& draw = getDrawingDisplayState(displayToken); - EXPECT_EQ(Case::Display::TYPE, draw.type); + EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual()); + EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL) ? std::nullopt + : Case::Display::DISPLAY_ID::get(), + draw.displayId); } template <typename Case> void HandleTransactionLockedTest::verifyPhysicalDisplayIsConnected() { // HWComposer should have an entry for the display - EXPECT_TRUE(hasHwcDisplay(Case::Display::HWC_DISPLAY_ID)); + EXPECT_TRUE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); - // The display should be set up as a built-in display. - static_assert(0 <= Case::Display::TYPE && - Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, - "Must use a valid physical display type index for the fixed-size array"); - auto& displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; - ASSERT_TRUE(displayToken != nullptr); + // SF should have a display token. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(*displayId) == 1); + auto& displayToken = mFlinger.mutablePhysicalDisplayTokens()[*displayId]; verifyDisplayIsConnected<Case>(displayToken); } @@ -1371,7 +1474,7 @@ void HandleTransactionLockedTest::ignoresHotplugConnectCommon() { // Postconditions // HWComposer should not have an entry for the display - EXPECT_FALSE(hasHwcDisplay(Case::Display::HWC_DISPLAY_ID)); + EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); } template <typename Case> @@ -1407,13 +1510,12 @@ void HandleTransactionLockedTest::processesHotplugDisconnectCommon() { // Postconditions // HWComposer should not have an entry for the display - EXPECT_FALSE(hasHwcDisplay(Case::Display::HWC_DISPLAY_ID)); + EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); - // The display should not be set up as a built-in display. - ASSERT_TRUE(0 <= Case::Display::TYPE && - Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES); - auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; - EXPECT_TRUE(displayToken == nullptr); + // SF should not have a display token. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(*displayId) == 0); // The existing token should have been removed verifyDisplayIsNotConnected(existing.token()); @@ -1500,13 +1602,12 @@ TEST_F(HandleTransactionLockedTest, processesHotplugConnectThenDisconnectPrimary // Postconditions // HWComposer should not have an entry for the display - EXPECT_FALSE(hasHwcDisplay(Case::Display::HWC_DISPLAY_ID)); + EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); - // The display should not be set up as a primary built-in display. - ASSERT_TRUE(0 <= Case::Display::TYPE && - Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES); - auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; - EXPECT_TRUE(displayToken == nullptr); + // SF should not have a display token. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(*displayId) == 0); } TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary) { @@ -1545,10 +1646,10 @@ TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary // The existing token should have been removed verifyDisplayIsNotConnected(existing.token()); - static_assert(0 <= Case::Display::TYPE && - Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, - "Display type must be a built-in display"); - EXPECT_NE(existing.token(), mFlinger.mutableDisplayTokens()[Case::Display::TYPE]); + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(*displayId) == 1); + EXPECT_NE(existing.token(), mFlinger.mutablePhysicalDisplayTokens()[*displayId]); // A new display should be connected in its place @@ -1578,13 +1679,12 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAdded) { // surface(producer) sp<BBinder> displayToken = new BBinder(); - DisplayDeviceState info; - info.type = Case::Display::TYPE; - info.isSecure = static_cast<bool>(Case::Display::SECURE); + DisplayDeviceState state; + state.isSecure = static_cast<bool>(Case::Display::SECURE); sp<mock::GraphicBufferProducer> surface{new mock::GraphicBufferProducer()}; - info.surface = surface; - mFlinger.mutableCurrentState().displays.add(displayToken, info); + state.surface = surface; + mFlinger.mutableCurrentState().displays.add(displayToken, state); // -------------------------------------------------------------------- // Call Expectations @@ -1646,11 +1746,10 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) { // surface. sp<BBinder> displayToken = new BBinder(); - DisplayDeviceState info; - info.type = Case::Display::TYPE; - info.isSecure = static_cast<bool>(Case::Display::SECURE); + DisplayDeviceState state; + state.isSecure = static_cast<bool>(Case::Display::SECURE); - mFlinger.mutableCurrentState().displays.add(displayToken, info); + mFlinger.mutableCurrentState().displays.add(displayToken, state); // -------------------------------------------------------------------- // Call Expectations @@ -1669,7 +1768,7 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) { // The drawing display state will be set from the current display state. ASSERT_TRUE(hasDrawingDisplayState(displayToken)); const auto& draw = getDrawingDisplayState(displayToken); - EXPECT_EQ(Case::Display::TYPE, draw.type); + EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual()); } TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) { @@ -1679,7 +1778,9 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) { // Preconditions // A virtual display is set up but is removed from the current state. - mFlinger.mutableHwcDisplayData().resize(3); + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + mFlinger.mutableHwcDisplayData()[*displayId] = {}; Case::Display::injectHwcDisplay(this); auto existing = Case::Display::makeFakeExistingDisplayInjector(this); existing.inject(); @@ -2799,9 +2900,10 @@ TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfVirtualDisplay // -------------------------------------------------------------------- // Preconditions - // We need to resize this so that the HWC thinks the virtual display - // is something it created. - mFlinger.mutableHwcDisplayData().resize(3); + // Insert display data so that the HWC thinks it created the virtual display. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + mFlinger.mutableHwcDisplayData()[*displayId] = {}; // A virtual display device is set up Case::Display::injectHwcDisplay(this); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c3534e83a..b046e4a83 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -178,10 +178,6 @@ public: layer->getBE().compositionInfo.hwc.sidebandStream = sidebandStream; } - void setLayerCompositionType(sp<Layer> layer, HWC2::Composition type) { - layer->getBE().mHwcLayers[DisplayDevice::DISPLAY_PRIMARY].compositionType = type; - }; - void setLayerPotentialCursor(sp<Layer> layer, bool potentialCursor) { layer->mPotentialCursor = potentialCursor; } @@ -200,7 +196,8 @@ public: auto resetDisplayState() { return mFlinger->resetDisplayState(); } - auto setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken, int32_t displayId, + auto setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken, + const std::optional<DisplayId>& displayId, const DisplayDeviceState& state, const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { @@ -263,7 +260,6 @@ public: auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } auto& mutableDisplays() { return mFlinger->mDisplays; } - auto& mutableDisplayTokens() { return mFlinger->mDisplayTokens; } auto& mutableDrawingState() { return mFlinger->mDrawingState; } auto& mutableEventControlThread() { return mFlinger->mEventControlThread; } auto& mutableEventQueue() { return mFlinger->mEventQueue; } @@ -273,6 +269,7 @@ public: auto& mutableInterceptor() { return mFlinger->mInterceptor; } auto& mutableMainThreadId() { return mFlinger->mMainThreadId; } auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; } + auto& mutablePhysicalDisplayTokens() { return mFlinger->mPhysicalDisplayTokens; } auto& mutablePrimaryDispSync() { return mFlinger->mPrimaryDispSync; } auto& mutablePrimaryHWVsyncEnabled() { return mFlinger->mPrimaryHWVsyncEnabled; } auto& mutableTexturePool() { return mFlinger->mTexturePool; } @@ -280,8 +277,13 @@ public: auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; } auto& mutableComposerSequenceId() { return mFlinger->getBE().mComposerSequenceId; } - auto& mutableHwcDisplayData() { return mFlinger->getBE().mHwc->mDisplayData; } - auto& mutableHwcDisplaySlots() { return mFlinger->getBE().mHwc->mHwcDisplaySlots; } + auto& mutableHwcDisplayData() { return mFlinger->getHwComposer().mDisplayData; } + auto& mutableHwcPhysicalDisplayIdMap() { + return mFlinger->getHwComposer().mPhysicalDisplayIdMap; + } + + auto& mutableInternalHwcDisplayId() { return mFlinger->getHwComposer().mInternalHwcDisplayId; } + auto& mutableExternalHwcDisplayId() { return mFlinger->getHwComposer().mExternalHwcDisplayId; } ~TestableSurfaceFlinger() { // All these pointer and container clears help ensure that GMock does @@ -333,8 +335,9 @@ public: static constexpr int32_t DEFAULT_DPI = 320; static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0; - FakeHwcDisplayInjector(DisplayDevice::DisplayType type, HWC2::DisplayType hwcDisplayType) - : mType(type), mHwcDisplayType(hwcDisplayType) {} + FakeHwcDisplayInjector(DisplayId displayId, HWC2::DisplayType hwcDisplayType, + bool isPrimary) + : mDisplayId(displayId), mHwcDisplayType(hwcDisplayType), mIsPrimary(isPrimary) {} auto& setHwcDisplayId(hwc2_display_t displayId) { mHwcDisplayId = displayId; @@ -403,17 +406,22 @@ public: display->mutableConfigs().emplace(mActiveConfig, config.build()); display->mutableIsConnected() = true; - ASSERT_TRUE(flinger->mutableHwcDisplayData().size() > static_cast<size_t>(mType)); - flinger->mutableHwcDisplayData()[mType] = HWComposer::DisplayData(); - flinger->mutableHwcDisplayData()[mType].hwcDisplay = display.get(); - flinger->mutableHwcDisplaySlots().emplace(mHwcDisplayId, mType); + flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = display.get(); + + if (mHwcDisplayType == HWC2::DisplayType::Physical) { + flinger->mutableHwcPhysicalDisplayIdMap().emplace(mHwcDisplayId, mDisplayId); + (mIsPrimary ? flinger->mutableInternalHwcDisplayId() + : flinger->mutableExternalHwcDisplayId()) = mHwcDisplayId; + } flinger->mFakeHwcDisplays.push_back(std::move(display)); } private: - DisplayDevice::DisplayType mType; - HWC2::DisplayType mHwcDisplayType; + const DisplayId mDisplayId; + const HWC2::DisplayType mHwcDisplayType; + const bool mIsPrimary; + hwc2_display_t mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID; int32_t mWidth = DEFAULT_WIDTH; int32_t mHeight = DEFAULT_HEIGHT; @@ -427,10 +435,13 @@ public: class FakeDisplayDeviceInjector { public: - FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, DisplayDevice::DisplayType type, - int32_t displayId) - : mFlinger(flinger), - mCreationArgs(flinger.mFlinger.get(), mDisplayToken, type, displayId) {} + FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, + const std::optional<DisplayId>& displayId, bool isVirtual, + bool isPrimary) + : mFlinger(flinger), mCreationArgs(flinger.mFlinger.get(), mDisplayToken, displayId) { + mCreationArgs.isVirtual = isVirtual; + mCreationArgs.isPrimary = isPrimary; + } sp<IBinder> token() const { return mDisplayToken; } @@ -497,7 +508,7 @@ public: sp<DisplayDevice> inject() { DisplayDeviceState state; - state.type = mCreationArgs.type; + state.displayId = mCreationArgs.isVirtual ? std::nullopt : mCreationArgs.displayId; state.isSecure = mCreationArgs.isSecure; sp<DisplayDevice> device = new DisplayDevice(std::move(mCreationArgs)); @@ -505,9 +516,9 @@ public: mFlinger.mutableCurrentState().displays.add(mDisplayToken, state); mFlinger.mutableDrawingState().displays.add(mDisplayToken, state); - if (state.type >= DisplayDevice::DISPLAY_PRIMARY && - state.type < DisplayDevice::DISPLAY_VIRTUAL) { - mFlinger.mutableDisplayTokens()[state.type] = mDisplayToken; + if (!mCreationArgs.isVirtual) { + LOG_ALWAYS_FATAL_IF(!state.displayId); + mFlinger.mutablePhysicalDisplayTokens()[*state.displayId] = mDisplayToken; } return device; |
