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

Commit 540730af authored by Steven Thomas's avatar Steven Thomas Committed by Ana Krulec
Browse files

Adding support for the setFrameRate() API to SurfaceFlinger path

- When choosing the max refresh rate in Layer History, check if
the layer has the bit set, if so use it.
- Disable touch boost/choosing config with max refresh rate,
when the layer has framerate set.

Test: Run unit test. Observe logs.
Test: Extend unit test to 10sec. Tap on screen while it's running.
      Observe logs. Tap, should not reset the max refresh rate.
Change-Id: Ibe2689964c9f92788ace1b08c3521f156cb47524
parent 6ebe801b
Loading
Loading
Loading
Loading
+41 −1
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@ namespace android::scheduler::impl {
namespace {

bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) {
    if (layer.getFrameRate() > .0f) {
        return layer.isVisible();
    }
    return layer.isVisible() && info.getLastUpdatedTime() >= threshold;
}

@@ -117,11 +120,32 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) {
                    // Layers should be organized by priority
                    ALOGD("Layer has priority: %d", priority);
                }
            }
        }
    }

    for (const auto& [weakLayer, info] : activeLayers()) {
        const bool recent = info->isRecentlyActive(now);
        auto layer = weakLayer.promote();
        // Only use the layer if the reference still exists.
        if (layer || CC_UNLIKELY(mTraceEnabled)) {
            float refreshRate = 0.f;
            // Default content refresh rate is only used when dealing with recent layers.
            if (recent) {
                refreshRate = info->getRefreshRate(now);
            }
            // Check if frame rate was set on layer.
            float frameRate = layer->getFrameRate();
            if (frameRate > 0.f) {
                // Override content detection refresh rate, if it was set.
                refreshRate = frameRate;
            }
            if (refreshRate > maxRefreshRate) {
                maxRefreshRate = refreshRate;
            }

            if (CC_UNLIKELY(mTraceEnabled)) {
                trace(activeLayer, std::round(refreshRate));
                trace(weakLayer, std::round(refreshRate));
            }
        }
    }
@@ -175,6 +199,22 @@ void LayerHistory::clear() {
    mActiveLayersEnd = 0;
}

bool LayerHistory::hasClientSpecifiedFrameRate() {
    std::lock_guard lock(mLock);
    for (const auto& [weakLayer, info] : activeLayers()) {
        auto layer = weakLayer.promote();
        if (layer) {
            float frameRate = layer->getFrameRate();
            // Found a layer that has a frame rate set on it.
            if (fabs(frameRate) > 0.f) {
                return true;
            }
        }
    }
    // Did not find any layers that have frame rate.
    return false;
}

} // namespace android::scheduler::impl

// TODO(b/129481165): remove the #pragma below and fix conversion issues
+7 −0
Original line number Diff line number Diff line
@@ -53,6 +53,9 @@ public:
    virtual Summary summarize(nsecs_t now) = 0;

    virtual void clear() = 0;

    // Checks whether any of the active layers have a desired frame rate bit set on them.
    virtual bool hasClientSpecifiedFrameRate() = 0;
};

namespace impl {
@@ -75,6 +78,10 @@ public:

    void clear() override;

    // Traverses all active layers and checks whether any of them have a desired frame
    // rate bit set on them.
    bool hasClientSpecifiedFrameRate() override;

private:
    friend class android::scheduler::LayerHistoryTest;
    friend TestableScheduler;
+34 −26
Original line number Diff line number Diff line
@@ -422,6 +422,13 @@ void Scheduler::resetIdleTimer() {
}

void Scheduler::notifyTouchEvent() {
    // Touch event will boost the refresh rate to performance.
    // Clear Layer History to get fresh FPS detection.
    // NOTE: Instead of checking all the layers, we should be checking the layer
    // that is currently on top. b/142507166 will give us this capability.
    if (mLayerHistory && !mLayerHistory->hasClientSpecifiedFrameRate()) {
        mLayerHistory->clear();

        if (mTouchTimer) {
            mTouchTimer->reset();
        }
@@ -429,11 +436,6 @@ void Scheduler::notifyTouchEvent() {
        if (mSupportKernelTimer && mIdleTimer) {
            mIdleTimer->reset();
        }

    // Touch event will boost the refresh rate to performance.
    // Clear Layer History to get fresh FPS detection
    if (mLayerHistory) {
        mLayerHistory->clear();
    }
}

@@ -533,9 +535,14 @@ HwcConfigIndexType Scheduler::calculateRefreshRateType() {
        return mRefreshRateConfigs.getCurrentRefreshRate().configId;
    }

    // If the layer history doesn't have the frame rate specified, use the old path. NOTE:
    // if we remove the kernel idle timer, and use our internal idle timer, this code will have to
    // be refactored.
    if (!mLayerHistory->hasClientSpecifiedFrameRate()) {
        // If Display Power is not in normal operation we want to be in performance mode.
        // When coming back to normal mode, a grace period is given with DisplayPowerTimer
    if (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset) {
        if (!mFeatures.isDisplayPowerStateNormal ||
            mFeatures.displayPowerTimer == TimerState::Reset) {
            return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
        }

@@ -553,6 +560,7 @@ HwcConfigIndexType Scheduler::calculateRefreshRateType() {
        if (mFeatures.contentDetection == ContentDetectionState::Off) {
            return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
        }
    }

    // Content detection is on, find the appropriate refresh rate with minimal error
    return mRefreshRateConfigs