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

Commit 715a2c13 authored by Lloyd Pique's avatar Lloyd Pique
Browse files

Determine displayType in SurfaceFlinger

This change eliminates an assumption that the first hotplug connect
event is for the primary display, and all other events are for the
external display.

Bug: 38464421
Test: Boots, settings app navigable
Change-Id: I753deb9a4e99a7b225ab89562c7acf4ce284dbf5
parent fcd86617
Loading
Loading
Loading
Loading
+2 −18
Original line number Diff line number Diff line
@@ -52,24 +52,13 @@ namespace {
class ComposerCallbackBridge : public Hwc2::IComposerCallback {
public:
    ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)
            : mCallback(callback), mSequenceId(sequenceId),
              mHasPrimaryDisplay(false) {}
            : mCallback(callback), mSequenceId(sequenceId) {}

    Return<void> onHotplug(Hwc2::Display display,
                           IComposerCallback::Connection conn) override
    {
        HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
        if (!mHasPrimaryDisplay) {
            LOG_ALWAYS_FATAL_IF(connection != HWC2::Connection::Connected,
                    "Initial onHotplug callback should be "
                    "primary display connected");
            mHasPrimaryDisplay = true;
            mCallback->onHotplugReceived(mSequenceId, display,
                                         connection, true);
        } else {
            mCallback->onHotplugReceived(mSequenceId, display,
                                         connection, false);
        }
        mCallback->onHotplugReceived(mSequenceId, display, connection);
        return Void();
    }

@@ -85,12 +74,9 @@ public:
        return Void();
    }

    bool HasPrimaryDisplay() { return mHasPrimaryDisplay; }

private:
    ComposerCallback* mCallback;
    int32_t mSequenceId;
    bool mHasPrimaryDisplay;
};

} // namespace anonymous
@@ -117,8 +103,6 @@ void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {
    sp<ComposerCallbackBridge> callbackBridge(
            new ComposerCallbackBridge(callback, sequenceId));
    mComposer->registerCallback(callbackBridge);
    LOG_ALWAYS_FATAL_IF(!callbackBridge->HasPrimaryDisplay(),
            "Registered composer callback but didn't get primary display");
}

// Required by HWC2 device
+1 −2
Original line number Diff line number Diff line
@@ -65,8 +65,7 @@ class Layer;
class ComposerCallback {
 public:
    virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
                                   Connection connection,
                                   bool primaryDisplay) = 0;
                                   Connection connection) = 0;
    virtual void onRefreshReceived(int32_t sequenceId,
                                   hwc2_display_t display) = 0;
    virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+13 −14
Original line number Diff line number Diff line
@@ -119,23 +119,22 @@ void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) {
    }
}

void HWComposer::onHotplug(hwc2_display_t displayId,
void HWComposer::onHotplug(hwc2_display_t displayId, int32_t displayType,
                           HWC2::Connection connection) {
    ALOGV("hotplug: %" PRIu64 ", %s", displayId,
    if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
        ALOGE("Invalid display type of %d", displayType);
        return;
    }

    ALOGV("hotplug: %" PRIu64 ", %s %s", displayId,
            displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external",
            to_string(connection).c_str());
    mHwcDevice->onHotplug(displayId, connection);
    if (!mDisplayData[0].hwcDisplay) {
        ALOGE_IF(connection != HWC2::Connection::Connected, "Assumed primary"
                " display would be connected");
        mDisplayData[0].hwcDisplay = mHwcDevice->getDisplayById(displayId);
        mHwcDisplaySlots[displayId] = 0;
    } else {
    // Disconnect is handled through HWComposer::disconnectDisplay via
    // SurfaceFlinger's onHotplugReceived callback handling
    if (connection == HWC2::Connection::Connected) {
            mDisplayData[1].hwcDisplay = mHwcDevice->getDisplayById(displayId);
            mHwcDisplaySlots[displayId] = 1;
        }
        mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(displayId);
        mHwcDisplaySlots[displayId] = displayType;
    }
}

+1 −1
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ public:
    // DisplayDevice::DisplayType of the display is returned as an output param.
    bool onVsync(hwc2_display_t displayId, int64_t timestamp,
                 int32_t* outDisplay);
    void onHotplug(hwc2_display_t displayId, HWC2::Connection connection);
    void onHotplug(hwc2_display_t displayId, int32_t displayType, HWC2::Connection connection);

    void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);

+37 −12
Original line number Diff line number Diff line
@@ -1263,14 +1263,10 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
    *compositorTiming = getBE().mCompositorTiming;
}

void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
        hwc2_display_t display, HWC2::Connection connection,
        bool primaryDisplay) {
    ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s, %s)",
          sequenceId, display,
          connection == HWC2::Connection::Connected ?
                  "connected" : "disconnected",
          primaryDisplay ? "primary" : "external");
void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
                                       HWC2::Connection connection) {
    ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s)", sequenceId, display,
          connection == HWC2::Connection::Connected ? "connected" : "disconnected");

    // Ignore events that do not have the right sequenceId.
    if (sequenceId != getBE().mComposerSequenceId) {
@@ -1283,7 +1279,7 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
    // acquire it here.
    ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);

    mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection, primaryDisplay});
    mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection});

    setTransactionFlags(eDisplayTransactionNeeded);
}
@@ -2044,17 +2040,46 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
    // here the transaction has been committed
}

DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display,
        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 primaryDisplayId =
            getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY);
    const auto externalDisplayId =
            getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL);
    if (primaryDisplayId && primaryDisplayId == display) {
        return DisplayDevice::DISPLAY_PRIMARY;
    } else if (externalDisplayId && externalDisplayId == display) {
        return  DisplayDevice::DISPLAY_EXTERNAL;
    } else if (connection == HWC2::Connection::Connected && !primaryDisplayId) {
        return DisplayDevice::DISPLAY_PRIMARY;
    } else if (connection == HWC2::Connection::Connected && !externalDisplayId) {
        return DisplayDevice::DISPLAY_EXTERNAL;
    }

    return DisplayDevice::DISPLAY_ID_INVALID;
}

void SurfaceFlinger::processDisplayHotplugEventsLocked() {
    for (const auto& event : mPendingHotplugEvents) {
        DisplayDevice::DisplayType displayType = event.isPrimaryDisplay ?
                DisplayDevice::DISPLAY_PRIMARY : DisplayDevice::DISPLAY_EXTERNAL;
        auto displayType = determineDisplayType(event.display, event.connection);
        if (displayType == DisplayDevice::DISPLAY_ID_INVALID) {
            ALOGW("Unable to determine the display type for display %" PRIu64, event.display);
            continue;
        }

        if (getBE().mHwc->isUsingVrComposer() && displayType == DisplayDevice::DISPLAY_EXTERNAL) {
            ALOGE("External displays are not supported by the vr hardware composer.");
            continue;
        }

        getBE().mHwc->onHotplug(event.display, event.connection);
        getBE().mHwc->onHotplug(event.display, displayType, event.connection);

        if (event.connection == HWC2::Connection::Connected) {
            ALOGV("Creating built in display %d", displayType);
Loading