Loading services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,7 @@ public: MOCK_METHOD3(allocateVirtualDisplay, MOCK_METHOD3(allocateVirtualDisplay, std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*)); std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*)); MOCK_METHOD2(allocatePhysicalDisplay, void(hwc2_display_t, DisplayId)); MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId)); MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId)); MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*)); MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*)); MOCK_METHOD3(getDeviceCompositionChanges, MOCK_METHOD3(getDeviceCompositionChanges, Loading services/surfaceflinger/DisplayHardware/HWComposer.cpp +94 −79 Original line number Original line Diff line number Diff line Loading @@ -205,56 +205,14 @@ bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId, std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, HWC2::Connection connection) { HWC2::Connection connection) { std::optional<DisplayIdentificationInfo> info; switch (connection) { case HWC2::Connection::Connected: if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) { return onHotplugConnect(hwcDisplayId); info = DisplayIdentificationInfo{.id = *displayId, case HWC2::Connection::Disconnected: .name = std::string(), return onHotplugDisconnect(hwcDisplayId); .deviceProductInfo = std::nullopt}; case HWC2::Connection::Invalid: } else { if (connection == HWC2::Connection::Disconnected) { ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId); return {}; return {}; } } info = onHotplugConnect(hwcDisplayId); if (!info) return {}; } ALOGV("%s: %s %s display %s with HWC ID %" PRIu64, __FUNCTION__, to_string(connection).c_str(), hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", to_string(info->id).c_str(), hwcDisplayId); if (connection == HWC2::Connection::Connected) { auto& displayData = mDisplayData[info->id]; // If we get a hotplug connected event for a display we already have, // destroy the display and recreate it. This will force us to requery // the display params and recreate all layers on that display. if (displayData.hwcDisplay != nullptr && displayData.hwcDisplay->isConnected()) { ALOGI("Hotplug connecting an already connected display." " Clearing old display state."); } displayData.hwcDisplay.reset(); auto newDisplay = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId, HWC2::DisplayType::Physical); newDisplay->setConnected(true); displayData.hwcDisplay = std::move(newDisplay); mPhysicalDisplayIdMap[hwcDisplayId] = info->id; } else if (connection == HWC2::Connection::Disconnected) { // The display will later be destroyed by a call to // destroyDisplay(). For now we just mark it disconnected. auto& displayData = mDisplayData[info->id]; if (displayData.hwcDisplay) { displayData.hwcDisplay->setConnected(false); } else { ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId); } // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay // via SurfaceFlinger's onHotplugReceived callback handling } return info; } } bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) { bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) { Loading Loading @@ -337,6 +295,22 @@ std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint return displayId; return displayId; } } void HWComposer::allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) { if (!mInternalHwcDisplayId) { mInternalHwcDisplayId = hwcDisplayId; } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) { mExternalHwcDisplayId = hwcDisplayId; } auto& displayData = mDisplayData[displayId]; auto newDisplay = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId, HWC2::DisplayType::Physical); newDisplay->setConnected(true); displayData.hwcDisplay = std::move(newDisplay); mPhysicalDisplayIdMap[hwcDisplayId] = displayId; } HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId, nullptr); RETURN_IF_INVALID_DISPLAY(displayId, nullptr); Loading Loading @@ -911,52 +885,93 @@ std::optional<hwc2_display_t> HWComposer::fromPhysicalDisplayId(DisplayId displa return {}; return {}; } } std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) { bool HWComposer::shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId, bool hasDisplayIdentificationData) const { if (isUsingVrComposer() && mInternalHwcDisplayId) { if (isUsingVrComposer() && mInternalHwcDisplayId) { ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); return {}; return true; } } if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) { ALOGE("Ignoring connection of display %" PRIu64 " without identification data", hwcDisplayId); return true; } if (!mHasMultiDisplaySupport && mInternalHwcDisplayId && mExternalHwcDisplayId) { ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId); return true; } return false; } std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) { std::optional<DisplayIdentificationInfo> info; if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) { info = DisplayIdentificationInfo{.id = *displayId, .name = std::string(), .deviceProductInfo = std::nullopt}; } else { uint8_t port; uint8_t port; DisplayIdentificationData data; DisplayIdentificationData data; const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data); const bool hasDisplayIdentificationData = getDisplayIdentificationData(hwcDisplayId, &port, &data); if (mPhysicalDisplayIdMap.empty()) { if (mPhysicalDisplayIdMap.empty()) { mHasMultiDisplaySupport = hasMultiDisplaySupport; mHasMultiDisplaySupport = hasDisplayIdentificationData; ALOGI("Switching to %s multi-display mode", ALOGI("Switching to %s multi-display mode", hasMultiDisplaySupport ? "generalized" : "legacy"); mHasMultiDisplaySupport ? "generalized" : "legacy"); } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) { ALOGE("Ignoring connection of display %" PRIu64 " without identification data", hwcDisplayId); return {}; } } std::optional<DisplayIdentificationInfo> info; if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) { return {}; } info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] { const bool isPrimary = !mInternalHwcDisplayId; if (mHasMultiDisplaySupport) { if (mHasMultiDisplaySupport) { info = parseDisplayIdentificationData(port, data); if (const auto info = parseDisplayIdentificationData(port, data)) { ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId); return *info; } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) { } ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId); ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId); return {}; } else { } else { ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64, ALOGW_IF(hasDisplayIdentificationData, hwcDisplayId); "Ignoring identification data for display %" PRIu64, hwcDisplayId); port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY; port = isPrimary ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL; } } if (!mInternalHwcDisplayId) { return DisplayIdentificationInfo{.id = getFallbackDisplayId(port), mInternalHwcDisplayId = hwcDisplayId; .name = isPrimary ? "Internal display" } else if (!mExternalHwcDisplayId) { : "External display", mExternalHwcDisplayId = hwcDisplayId; .deviceProductInfo = std::nullopt}; }(); } } if (info) return info; if (!isConnected(info->id)) { allocatePhysicalDisplay(hwcDisplayId, info->id); } return info; } return DisplayIdentificationInfo{.id = getFallbackDisplayId(port), std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect( .name = hwcDisplayId == mInternalHwcDisplayId hwc2_display_t hwcDisplayId) { ? "Internal display" const auto displayId = toPhysicalDisplayId(hwcDisplayId); : "External display", if (!displayId) { ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId); return {}; } // The display will later be destroyed by a call to // destroyDisplay(). For now we just mark it disconnected. if (isConnected(*displayId)) { mDisplayData[*displayId].hwcDisplay->setConnected(false); } else { ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId); } // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay // via SurfaceFlinger's onHotplugReceived callback handling return DisplayIdentificationInfo{.id = *displayId, .name = std::string(), .deviceProductInfo = std::nullopt}; .deviceProductInfo = std::nullopt}; } } Loading services/surfaceflinger/DisplayHardware/HWComposer.h +10 −0 Original line number Original line Diff line number Diff line Loading @@ -77,6 +77,8 @@ public: virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, ui::PixelFormat* format) = 0; ui::PixelFormat* format) = 0; virtual void allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) = 0; // Attempts to create a new layer on this display // Attempts to create a new layer on this display virtual HWC2::Layer* createLayer(DisplayId displayId) = 0; virtual HWC2::Layer* createLayer(DisplayId displayId) = 0; // Destroy a previously created layer // Destroy a previously created layer Loading Loading @@ -164,6 +166,7 @@ public: // Returns stable display ID (and display name on connection of new or previously disconnected // Returns stable display ID (and display name on connection of new or previously disconnected // display), or std::nullopt if hotplug event was ignored. // display), or std::nullopt if hotplug event was ignored. // This function is called from SurfaceFlinger. virtual std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId, virtual std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId, HWC2::Connection connection) = 0; HWC2::Connection connection) = 0; Loading Loading @@ -238,6 +241,9 @@ public: std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, ui::PixelFormat* format) override; ui::PixelFormat* format) override; // Called from SurfaceFlinger, when the state for a new physical display needs to be recreated. void allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) override; // Attempts to create a new layer on this display // Attempts to create a new layer on this display HWC2::Layer* createLayer(DisplayId displayId) override; HWC2::Layer* createLayer(DisplayId displayId) override; // Destroy a previously created layer // Destroy a previously created layer Loading Loading @@ -361,6 +367,10 @@ private: friend TestableSurfaceFlinger; friend TestableSurfaceFlinger; std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId); std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId); std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hwc2_display_t hwcDisplayId); bool shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId, bool hasDisplayIdentificationData) const; void loadCapabilities(); void loadCapabilities(); void loadLayerMetadataSupport(); void loadLayerMetadataSupport(); uint32_t getMaxVirtualDisplayCount() const; uint32_t getMaxVirtualDisplayCount() const; Loading Loading
services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,7 @@ public: MOCK_METHOD3(allocateVirtualDisplay, MOCK_METHOD3(allocateVirtualDisplay, std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*)); std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*)); MOCK_METHOD2(allocatePhysicalDisplay, void(hwc2_display_t, DisplayId)); MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId)); MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId)); MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*)); MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*)); MOCK_METHOD3(getDeviceCompositionChanges, MOCK_METHOD3(getDeviceCompositionChanges, Loading
services/surfaceflinger/DisplayHardware/HWComposer.cpp +94 −79 Original line number Original line Diff line number Diff line Loading @@ -205,56 +205,14 @@ bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId, std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, HWC2::Connection connection) { HWC2::Connection connection) { std::optional<DisplayIdentificationInfo> info; switch (connection) { case HWC2::Connection::Connected: if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) { return onHotplugConnect(hwcDisplayId); info = DisplayIdentificationInfo{.id = *displayId, case HWC2::Connection::Disconnected: .name = std::string(), return onHotplugDisconnect(hwcDisplayId); .deviceProductInfo = std::nullopt}; case HWC2::Connection::Invalid: } else { if (connection == HWC2::Connection::Disconnected) { ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId); return {}; return {}; } } info = onHotplugConnect(hwcDisplayId); if (!info) return {}; } ALOGV("%s: %s %s display %s with HWC ID %" PRIu64, __FUNCTION__, to_string(connection).c_str(), hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", to_string(info->id).c_str(), hwcDisplayId); if (connection == HWC2::Connection::Connected) { auto& displayData = mDisplayData[info->id]; // If we get a hotplug connected event for a display we already have, // destroy the display and recreate it. This will force us to requery // the display params and recreate all layers on that display. if (displayData.hwcDisplay != nullptr && displayData.hwcDisplay->isConnected()) { ALOGI("Hotplug connecting an already connected display." " Clearing old display state."); } displayData.hwcDisplay.reset(); auto newDisplay = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId, HWC2::DisplayType::Physical); newDisplay->setConnected(true); displayData.hwcDisplay = std::move(newDisplay); mPhysicalDisplayIdMap[hwcDisplayId] = info->id; } else if (connection == HWC2::Connection::Disconnected) { // The display will later be destroyed by a call to // destroyDisplay(). For now we just mark it disconnected. auto& displayData = mDisplayData[info->id]; if (displayData.hwcDisplay) { displayData.hwcDisplay->setConnected(false); } else { ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId); } // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay // via SurfaceFlinger's onHotplugReceived callback handling } return info; } } bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) { bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) { Loading Loading @@ -337,6 +295,22 @@ std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint return displayId; return displayId; } } void HWComposer::allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) { if (!mInternalHwcDisplayId) { mInternalHwcDisplayId = hwcDisplayId; } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) { mExternalHwcDisplayId = hwcDisplayId; } auto& displayData = mDisplayData[displayId]; auto newDisplay = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId, HWC2::DisplayType::Physical); newDisplay->setConnected(true); displayData.hwcDisplay = std::move(newDisplay); mPhysicalDisplayIdMap[hwcDisplayId] = displayId; } HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId, nullptr); RETURN_IF_INVALID_DISPLAY(displayId, nullptr); Loading Loading @@ -911,52 +885,93 @@ std::optional<hwc2_display_t> HWComposer::fromPhysicalDisplayId(DisplayId displa return {}; return {}; } } std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) { bool HWComposer::shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId, bool hasDisplayIdentificationData) const { if (isUsingVrComposer() && mInternalHwcDisplayId) { if (isUsingVrComposer() && mInternalHwcDisplayId) { ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); return {}; return true; } } if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) { ALOGE("Ignoring connection of display %" PRIu64 " without identification data", hwcDisplayId); return true; } if (!mHasMultiDisplaySupport && mInternalHwcDisplayId && mExternalHwcDisplayId) { ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId); return true; } return false; } std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) { std::optional<DisplayIdentificationInfo> info; if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) { info = DisplayIdentificationInfo{.id = *displayId, .name = std::string(), .deviceProductInfo = std::nullopt}; } else { uint8_t port; uint8_t port; DisplayIdentificationData data; DisplayIdentificationData data; const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data); const bool hasDisplayIdentificationData = getDisplayIdentificationData(hwcDisplayId, &port, &data); if (mPhysicalDisplayIdMap.empty()) { if (mPhysicalDisplayIdMap.empty()) { mHasMultiDisplaySupport = hasMultiDisplaySupport; mHasMultiDisplaySupport = hasDisplayIdentificationData; ALOGI("Switching to %s multi-display mode", ALOGI("Switching to %s multi-display mode", hasMultiDisplaySupport ? "generalized" : "legacy"); mHasMultiDisplaySupport ? "generalized" : "legacy"); } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) { ALOGE("Ignoring connection of display %" PRIu64 " without identification data", hwcDisplayId); return {}; } } std::optional<DisplayIdentificationInfo> info; if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) { return {}; } info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] { const bool isPrimary = !mInternalHwcDisplayId; if (mHasMultiDisplaySupport) { if (mHasMultiDisplaySupport) { info = parseDisplayIdentificationData(port, data); if (const auto info = parseDisplayIdentificationData(port, data)) { ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId); return *info; } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) { } ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId); ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId); return {}; } else { } else { ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64, ALOGW_IF(hasDisplayIdentificationData, hwcDisplayId); "Ignoring identification data for display %" PRIu64, hwcDisplayId); port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY; port = isPrimary ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL; } } if (!mInternalHwcDisplayId) { return DisplayIdentificationInfo{.id = getFallbackDisplayId(port), mInternalHwcDisplayId = hwcDisplayId; .name = isPrimary ? "Internal display" } else if (!mExternalHwcDisplayId) { : "External display", mExternalHwcDisplayId = hwcDisplayId; .deviceProductInfo = std::nullopt}; }(); } } if (info) return info; if (!isConnected(info->id)) { allocatePhysicalDisplay(hwcDisplayId, info->id); } return info; } return DisplayIdentificationInfo{.id = getFallbackDisplayId(port), std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect( .name = hwcDisplayId == mInternalHwcDisplayId hwc2_display_t hwcDisplayId) { ? "Internal display" const auto displayId = toPhysicalDisplayId(hwcDisplayId); : "External display", if (!displayId) { ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId); return {}; } // The display will later be destroyed by a call to // destroyDisplay(). For now we just mark it disconnected. if (isConnected(*displayId)) { mDisplayData[*displayId].hwcDisplay->setConnected(false); } else { ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId); } // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay // via SurfaceFlinger's onHotplugReceived callback handling return DisplayIdentificationInfo{.id = *displayId, .name = std::string(), .deviceProductInfo = std::nullopt}; .deviceProductInfo = std::nullopt}; } } Loading
services/surfaceflinger/DisplayHardware/HWComposer.h +10 −0 Original line number Original line Diff line number Diff line Loading @@ -77,6 +77,8 @@ public: virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, ui::PixelFormat* format) = 0; ui::PixelFormat* format) = 0; virtual void allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) = 0; // Attempts to create a new layer on this display // Attempts to create a new layer on this display virtual HWC2::Layer* createLayer(DisplayId displayId) = 0; virtual HWC2::Layer* createLayer(DisplayId displayId) = 0; // Destroy a previously created layer // Destroy a previously created layer Loading Loading @@ -164,6 +166,7 @@ public: // Returns stable display ID (and display name on connection of new or previously disconnected // Returns stable display ID (and display name on connection of new or previously disconnected // display), or std::nullopt if hotplug event was ignored. // display), or std::nullopt if hotplug event was ignored. // This function is called from SurfaceFlinger. virtual std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId, virtual std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId, HWC2::Connection connection) = 0; HWC2::Connection connection) = 0; Loading Loading @@ -238,6 +241,9 @@ public: std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height, ui::PixelFormat* format) override; ui::PixelFormat* format) override; // Called from SurfaceFlinger, when the state for a new physical display needs to be recreated. void allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) override; // Attempts to create a new layer on this display // Attempts to create a new layer on this display HWC2::Layer* createLayer(DisplayId displayId) override; HWC2::Layer* createLayer(DisplayId displayId) override; // Destroy a previously created layer // Destroy a previously created layer Loading Loading @@ -361,6 +367,10 @@ private: friend TestableSurfaceFlinger; friend TestableSurfaceFlinger; std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId); std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId); std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hwc2_display_t hwcDisplayId); bool shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId, bool hasDisplayIdentificationData) const; void loadCapabilities(); void loadCapabilities(); void loadLayerMetadataSupport(); void loadLayerMetadataSupport(); uint32_t getMaxVirtualDisplayCount() const; uint32_t getMaxVirtualDisplayCount() const; Loading