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

Commit d3b5c5db authored by Marin Shalamanov's avatar Marin Shalamanov
Browse files

SF: Requery display modes if the active mode is not supported

Some TV devices send two hotplug events immediately one after another
during startup. Because we query the active display mode
and the supported modes in two separete calls to HWC it's possible
to get an active mode, which is not in the list of supported modes.

If this happens we requery the display modes up to 3 times. If the
problem still persists we throw a fatal error.

Bug: 175678215
Bug: 159590486
Test: check that device boots
Test: plug HDMI out and it
Change-Id: I94dbadac4eb75ed659ede6299df0c3459ed6c74e
parent f22e6acb
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -91,6 +91,12 @@ public:
        int32_t dpiX = -1;
        int32_t dpiY = -1;
        int32_t configGroup = -1;

        friend std::ostream& operator<<(std::ostream& os, const HWCDisplayMode& mode) {
            return os << "id=" << mode.hwcId << " res=" << mode.width << "x" << mode.height
                      << " vsyncPeriod=" << mode.vsyncPeriod << " dpi=" << mode.dpiX << "x"
                      << mode.dpiY << " group=" << mode.configGroup;
        }
    };

    virtual ~HWComposer();
+34 −13
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@
#include "DisplayHardware/DisplayIdentification.h"
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/Hal.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
#include "DisplayRenderArea.h"
#include "EffectLayer.h"
@@ -131,6 +132,7 @@
#include "TimeStats/TimeStats.h"
#include "android-base/parseint.h"
#include "android-base/stringprintf.h"
#include "android-base/strings.h"

#define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock)

@@ -2306,8 +2308,28 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) {
    // here the transaction has been committed
}

DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId displayId) const {
    const auto hwcModes = getHwComposer().getModes(displayId);
void SurfaceFlinger::loadDisplayModes(PhysicalDisplayId displayId, DisplayModes& outModes,
                                      DisplayModePtr& outActiveMode) const {
    std::vector<HWComposer::HWCDisplayMode> hwcModes;
    std::optional<hal::HWDisplayId> activeModeHwcId;
    bool activeModeIsSupported;
    int attempt = 0;
    constexpr int kMaxAttempts = 3;
    do {
        hwcModes = getHwComposer().getModes(displayId);
        activeModeHwcId = getHwComposer().getActiveMode(displayId);
        LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active mode");

        activeModeIsSupported =
                std::any_of(hwcModes.begin(), hwcModes.end(),
                            [activeModeHwcId](const HWComposer::HWCDisplayMode& mode) {
                                return mode.hwcId == *activeModeHwcId;
                            });
    } while (!activeModeIsSupported && ++attempt < kMaxAttempts);
    LOG_ALWAYS_FATAL_IF(!activeModeIsSupported,
                        "After %d attempts HWC still returns an active mode which is not"
                        " supported. Active mode ID = %" PRIu64 " . Supported modes = %s",
                        kMaxAttempts, *activeModeHwcId, base::Join(hwcModes, ", ").c_str());

    DisplayModes oldModes;

@@ -2345,10 +2367,15 @@ DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId display

    if (modesAreSame) {
        // The supported modes have not changed, keep the old IDs.
        return oldModes;
        outModes = oldModes;
    } else {
        outModes = newModes;
    }

    return newModes;
    outActiveMode = *std::find_if(outModes.begin(), outModes.end(),
                                  [activeModeHwcId](const DisplayModePtr& mode) {
                                      return mode->getHwcId() == *activeModeHwcId;
                                  });
}

void SurfaceFlinger::processDisplayHotplugEventsLocked() {
@@ -2364,15 +2391,9 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() {
        const auto it = mPhysicalDisplayTokens.find(displayId);

        if (event.connection == hal::Connection::CONNECTED) {
            auto supportedModes = loadSupportedDisplayModes(displayId);
            const auto activeModeHwcId = getHwComposer().getActiveMode(displayId);
            LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active mode");

            const auto activeMode = *std::find_if(supportedModes.begin(), supportedModes.end(),
                                                  [activeModeHwcId](const DisplayModePtr& mode) {
                                                      return mode->getHwcId() == *activeModeHwcId;
                                                  });
            // TODO(b/175678215) Handle the case when activeMode is not in supportedModes
            DisplayModes supportedModes;
            DisplayModePtr activeMode;
            loadDisplayModes(displayId, supportedModes, activeMode);

            if (it == mPhysicalDisplayTokens.end()) {
                ALOGV("Creating display %s", to_string(displayId).c_str());
+2 −1
Original line number Diff line number Diff line
@@ -906,7 +906,8 @@ private:
    /*
     * Display management
     */
    DisplayModes loadSupportedDisplayModes(PhysicalDisplayId) const REQUIRES(mStateLock);
    void loadDisplayModes(PhysicalDisplayId displayId, DisplayModes& outModes,
                          DisplayModePtr& outActiveMode) const REQUIRES(mStateLock);
    sp<DisplayDevice> setupNewDisplayDeviceInternal(
            const wp<IBinder>& displayToken,
            std::shared_ptr<compositionengine::Display> compositionDisplay,