Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a96e7fb5 authored by Marin Shalamanov's avatar Marin Shalamanov Committed by Automerger Merge Worker
Browse files

Merge "SF: Refactor HWComposer::onHotplug()" into rvc-dev am: cf0d051a am: 7b571968

Change-Id: Ia1fbf27648186491ecb3e576b2c962f6fa70139f
parents 644fc311 7b571968
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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,
+94 −79
Original line number Original line Diff line number Diff line
@@ -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) {
@@ -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);


@@ -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};
}
}


+10 −0
Original line number Original line Diff line number Diff line
@@ -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
@@ -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;


@@ -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
@@ -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;