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

Commit 7d171b07 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "SurfaceFlinger: use scheduler::RefreshRateConfigs in setRefreshRateTo"

parents 1441760c 1902d072
Loading
Loading
Loading
Loading
+16 −13
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ namespace android {
namespace scheduler {

/**
 * This class is used to encapsulate configuration for refresh rates. It holds infomation
 * This class is used to encapsulate configuration for refresh rates. It holds information
 * about available refresh rates on the device, and the mapping between the numbers and human
 * readable names.
 */
@@ -40,8 +40,6 @@ public:
    enum class RefreshRateType { POWER_SAVING, DEFAULT, PERFORMANCE };

    struct RefreshRate {
        // Type of the refresh rate.
        RefreshRateType type;
        // This config ID corresponds to the position of the config in the vector that is stored
        // on the device.
        int configId;
@@ -59,13 +57,16 @@ public:
    }
    ~RefreshRateConfigs() = default;

    const std::vector<RefreshRate>& getRefreshRates() { return mRefreshRates; }
    const std::unordered_map<RefreshRateType, RefreshRate>& getRefreshRates() {
        return mRefreshRates;
    }
    const RefreshRate& getRefreshRate(RefreshRateType type) { return mRefreshRates[type]; }

private:
    void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
        // This is the rate that HWC encapsulates right now when the device is in DOZE mode.
        mRefreshRates.push_back(
                RefreshRate{RefreshRateType::POWER_SAVING, SCREEN_OFF_CONFIG_ID, "ScreenOff", 0});
        mRefreshRates.emplace(RefreshRateType::POWER_SAVING,
                              RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0});

        if (configs.size() < 1) {
            ALOGE("Device does not have valid configs. Config size is 0.");
@@ -88,9 +89,10 @@ private:
        nsecs_t vsyncPeriod = configIdToVsyncPeriod[0].second;
        if (vsyncPeriod != 0) {
            const float fps = 1e9 / vsyncPeriod;
            mRefreshRates.push_back(
                    RefreshRate{RefreshRateType::DEFAULT, configIdToVsyncPeriod[0].first,
                                base::StringPrintf("%2.ffps", fps), static_cast<uint32_t>(fps)});
            mRefreshRates.emplace(RefreshRateType::DEFAULT,
                                  RefreshRate{configIdToVsyncPeriod[0].first,
                                              base::StringPrintf("%2.ffps", fps),
                                              static_cast<uint32_t>(fps)});
        }

        if (configs.size() < 2) {
@@ -102,13 +104,14 @@ private:
        vsyncPeriod = configIdToVsyncPeriod[1].second;
        if (vsyncPeriod != 0) {
            const float fps = 1e9 / vsyncPeriod;
            mRefreshRates.push_back(
                    RefreshRate{RefreshRateType::PERFORMANCE, configIdToVsyncPeriod[1].first,
                                base::StringPrintf("%2.ffps", fps), static_cast<uint32_t>(fps)});
            mRefreshRates.emplace(RefreshRateType::PERFORMANCE,
                                  RefreshRate{configIdToVsyncPeriod[1].first,
                                              base::StringPrintf("%2.ffps", fps),
                                              static_cast<uint32_t>(fps)});
        }
    }

    std::vector<RefreshRate> mRefreshRates;
    std::unordered_map<RefreshRateType, RefreshRate> mRefreshRates;
};

} // namespace scheduler
+6 −7
Original line number Diff line number Diff line
@@ -41,10 +41,9 @@ class RefreshRateStats {
    static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR;

public:
    explicit RefreshRateStats(
            const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
    explicit RefreshRateStats(const std::shared_ptr<RefreshRateConfigs>& refreshRateConfigs,
                              const std::shared_ptr<TimeStats>& timeStats)
          : mRefreshRateConfigs(std::make_unique<RefreshRateConfigs>(configs)),
          : mRefreshRateConfigs(refreshRateConfigs),
            mTimeStats(timeStats),
            mPreviousRecordedTime(systemTime()) {}
    ~RefreshRateStats() = default;
@@ -84,7 +83,7 @@ public:
        flushTime();

        std::unordered_map<std::string, int64_t> totalTime;
        for (auto config : mRefreshRateConfigs->getRefreshRates()) {
        for (auto [type, config] : mRefreshRateConfigs->getRefreshRates()) {
            int64_t totalTimeForConfig = 0;
            if (mConfigModesTotalTime.find(config.configId) != mConfigModesTotalTime.end()) {
                totalTimeForConfig = mConfigModesTotalTime.at(config.configId);
@@ -124,7 +123,7 @@ private:
        mPreviousRecordedTime = currentTime;

        mConfigModesTotalTime[mode] += timeElapsedMs;
        for (const auto& config : mRefreshRateConfigs->getRefreshRates()) {
        for (const auto& [type, config] : mRefreshRateConfigs->getRefreshRates()) {
            if (config.configId == mode) {
                mTimeStats->recordRefreshRate(config.fps, timeElapsed);
            }
@@ -143,7 +142,7 @@ private:
    }

    // Keeps information about refresh rate configs that device has.
    std::unique_ptr<RefreshRateConfigs> mRefreshRateConfigs;
    std::shared_ptr<RefreshRateConfigs> mRefreshRateConfigs;

    // Aggregate refresh rate statistics for telemetry.
    std::shared_ptr<TimeStats> mTimeStats;
+21 −56
Original line number Diff line number Diff line
@@ -201,9 +201,6 @@ const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
const String16 sDump("android.permission.DUMP");

constexpr float kDefaultRefreshRate = 60.f;
constexpr float kPerformanceRefreshRate = 90.f;

// ---------------------------------------------------------------------------
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -712,8 +709,10 @@ void SurfaceFlinger::init() {
            setRefreshRateTo(RefreshRateType::PERFORMANCE, ConfigEvent::None);
        });
    }
    mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
                                                                              *display->getId()),
    mRefreshRateConfigs[*display->getId()] = std::make_shared<scheduler::RefreshRateConfigs>(
            getHwComposer().getConfigs(*display->getId()));
    mRefreshRateStats =
            std::make_unique<scheduler::RefreshRateStats>(mRefreshRateConfigs[*display->getId()],
                                                          mTimeStats);

    ALOGV("Done initializing");
@@ -921,14 +920,6 @@ void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int
                                            ConfigEvent event) {
    ATRACE_CALL();

    Vector<DisplayInfo> configs;
    // Lock is acquired by setRefreshRateTo.
    getDisplayConfigsLocked(displayToken, &configs);
    if (mode < 0 || mode >= static_cast<int>(configs.size())) {
        ALOGE("Attempt to set active config %d for display with %zu configs", mode, configs.size());
        return;
    }

    // Lock is acquired by setRefreshRateTo.
    const auto display = getDisplayDeviceLocked(displayToken);
    if (!display) {
@@ -1426,6 +1417,8 @@ bool SurfaceFlinger::isConfigAllowed(const DisplayId& displayId, int32_t config)
}

void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, ConfigEvent event) {
    ATRACE_CALL();

    mPhaseOffsets->setRefreshRateType(refreshRate);

    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
@@ -1435,47 +1428,23 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, ConfigEvent e
        return;
    }

    // TODO(b/113612090): There should be a message queue flush here. Because this esentially
    // runs on a mainthread, we cannot call postMessageSync. This can be resolved in a better
    // manner, once the setActiveConfig is synchronous, and is executed at a known time in a
    // refresh cycle.

    // Don't do any updating if the current fps is the same as the new one.
    const nsecs_t currentVsyncPeriod = getVsyncPeriod();
    if (currentVsyncPeriod == 0) {
        return;
    }

    // TODO(b/113612090): Consider having an enum value for correct refresh rates, rather than
    // floating numbers.
    const float currentFps = 1e9 / currentVsyncPeriod;
    const float newFps = refreshRate == RefreshRateType::PERFORMANCE ? kPerformanceRefreshRate
                                                                     : kDefaultRefreshRate;
    if (std::abs(currentFps - newFps) <= 1) {
        return;
    }

    const auto displayId = getInternalDisplayIdLocked();
    LOG_ALWAYS_FATAL_IF(!displayId);
    const auto displayToken = getInternalDisplayTokenLocked();

    auto configs = getHwComposer().getConfigs(*displayId);
    for (int i = 0; i < configs.size(); i++) {
        if (!isConfigAllowed(*displayId, i)) {
            ALOGV("Skipping config %d as it is not part of allowed configs", i);
            continue;
    auto desiredConfigId = mRefreshRateConfigs[*displayId]->getRefreshRate(refreshRate).configId;
    const auto display = getDisplayDeviceLocked(displayToken);
    if (desiredConfigId == display->getActiveConfig()) {
        return;
    }

        const nsecs_t vsyncPeriod = configs.at(i)->getVsyncPeriod();
        if (vsyncPeriod == 0) {
            continue;
        }
        const float fps = 1e9 / vsyncPeriod;
        // TODO(b/113612090): There should be a better way at determining which config
        // has the right refresh rate.
        if (std::abs(fps - newFps) <= 1) {
            setDesiredActiveConfig(getInternalDisplayTokenLocked(), i, event);
        }
    if (!isConfigAllowed(*displayId, desiredConfigId)) {
        ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId);
        return;
    }

    setDesiredActiveConfig(getInternalDisplayTokenLocked(), desiredConfigId, event);
}

void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
@@ -5677,17 +5646,13 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal(
    // make sure that the current config is still allowed
    int currentConfigIndex = getHwComposer().getActiveConfigIndex(*displayId);
    if (!isConfigAllowed(*displayId, currentConfigIndex)) {
        // TODO(b/122906558): stop querying HWC for the available configs and instead use the cached
        // configs queried on boot
        auto configs = getHwComposer().getConfigs(*displayId);

        for (int i = 0; i < configs.size(); i++) {
            if (isConfigAllowed(*displayId, i)) {
        for (const auto& [type, config] : mRefreshRateConfigs[*displayId]->getRefreshRates()) {
            if (isConfigAllowed(*displayId, config.configId)) {
                // TODO: we switch to the first allowed config. In the future
                // we may want to enhance this logic to pick a similar config
                // to the current one
                ALOGV("Old config is not allowed - switching to config %d", i);
                setDesiredActiveConfig(displayToken, i, ConfigEvent::Changed);
                ALOGV("Old config is not allowed - switching to config %d", config.configId);
                setDesiredActiveConfig(displayToken, config.configId, ConfigEvent::Changed);
                break;
            }
        }
+3 −0
Original line number Diff line number Diff line
@@ -1116,6 +1116,9 @@ private:
    sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
    std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;

    std::unordered_map<DisplayId, std::shared_ptr<scheduler::RefreshRateConfigs>>
            mRefreshRateConfigs;

    std::mutex mAllowedConfigsLock;
    std::unordered_map<DisplayId, std::unique_ptr<const AllowedDisplayConfigs>> mAllowedConfigs
            GUARDED_BY(mAllowedConfigsLock);
+3 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ protected:

    std::unique_ptr<RefreshRateStats> mRefreshRateStats;
    std::shared_ptr<android::mock::TimeStats> mTimeStats;
    std::shared_ptr<RefreshRateConfigs> mRefreshRateConfigs;
};

RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -61,7 +62,8 @@ RefreshRateStatsTest::~RefreshRateStatsTest() {

void RefreshRateStatsTest::init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs) {
    mTimeStats = std::make_shared<android::mock::TimeStats>();
    mRefreshRateStats = std::make_unique<RefreshRateStats>(configs, mTimeStats);
    mRefreshRateConfigs = std::make_shared<RefreshRateConfigs>(configs);
    mRefreshRateStats = std::make_unique<RefreshRateStats>(mRefreshRateConfigs, mTimeStats);
}

namespace {