diff options
| author | Dominik Laskowski <domlaskowski@google.com> | 2018-05-24 15:50:06 -0700 |
|---|---|---|
| committer | Dominik Laskowski <domlaskowski@google.com> | 2018-11-08 11:04:49 -0800 |
| commit | 075d317063d815430d3a45acc7292e0681f73ee5 (patch) | |
| tree | e692d15875e0143d9917ee843856b8bcdf125e2c /services/surfaceflinger | |
| parent | b04f98a270fa393232068b7423be765e823ddf50 (diff) | |
| download | android_frameworks_native-075d317063d815430d3a45acc7292e0681f73ee5.tar.gz android_frameworks_native-075d317063d815430d3a45acc7292e0681f73ee5.tar.bz2 android_frameworks_native-075d317063d815430d3a45acc7292e0681f73ee5.zip | |
SF: Generalize display management
This CL enables SF to manage an arbitrary number of physical displays.
Previously, displays were identified by 32-bit IDs, where 0 is the
internal display, 1 is the external display, [2, INT32_MAX] are HWC
virtual displays, and -1 represents an invalid display or a non-HWC
virtual display.
If the HWC provides display identification data, SF now allocates 64-bit
display IDs for physical and HWC virtual displays. The IDs are expressed
using an option type, where the null value represents an invalid display
or non-HWC virtual display. Without HWC support, SF falls back to legacy
behavior with at most two physical displays.
The dynamic display IDs are translated to the legacy constants at the
SF/DMS boundary, as a stopgap until the framework is generalized.
Bug: 74619554
Test: Connect 3 displays and create virtual displays on HWC 2.2 and 2.3
Test: libsurfaceflinger_unittest
Test: SurfaceFlinger_test
Change-Id: I0a4a57b6ab7de2dbcf719a4eb1a19a133694012e
Diffstat (limited to 'services/surfaceflinger')
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; |
