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

Commit 3610fce8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "SF: Move toggleKernelIdleTimer to DMC" into main

parents 8a13964f 43839679
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@
#include "Display/DisplaySnapshot.h"
#include "DisplayHardware/HWComposer.h"

#include <android-base/properties.h>
#include <common/FlagManager.h>
#include <common/trace.h>
#include <ftl/concat.h>
#include <ftl/expected.h>
#include <log/log.h>
@@ -237,4 +239,63 @@ void DisplayModeController::setActiveModeLocked(PhysicalDisplayId displayId, Dis
    }
}

void DisplayModeController::updateKernelIdleTimer(PhysicalDisplayId displayId) {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();

    const auto controllerOpt = displayPtr->selectorPtr->kernelIdleTimerController();
    if (!controllerOpt) return;

    using KernelIdleTimerAction = scheduler::RefreshRateSelector::KernelIdleTimerAction;

    switch (displayPtr->selectorPtr->getIdleTimerAction()) {
        case KernelIdleTimerAction::TurnOff:
            if (displayPtr->isKernelIdleTimerEnabled) {
                SFTRACE_INT("KernelIdleTimer", 0);
                updateKernelIdleTimer(displayId, std::chrono::milliseconds::zero(), *controllerOpt);
                displayPtr->isKernelIdleTimerEnabled = false;
            }
            break;
        case KernelIdleTimerAction::TurnOn:
            if (!displayPtr->isKernelIdleTimerEnabled) {
                SFTRACE_INT("KernelIdleTimer", 1);
                const auto timeout = displayPtr->selectorPtr->getIdleTimerTimeout();
                updateKernelIdleTimer(displayId, timeout, *controllerOpt);
                displayPtr->isKernelIdleTimerEnabled = true;
            }
            break;
    }
}

void DisplayModeController::updateKernelIdleTimer(PhysicalDisplayId displayId,
                                                  std::chrono::milliseconds timeout,
                                                  KernelIdleTimerController controller) {
    switch (controller) {
        case KernelIdleTimerController::HwcApi:
            mComposerPtr->setIdleTimerEnabled(displayId, timeout);
            break;

        case KernelIdleTimerController::Sysprop:
            using namespace std::string_literals;
            base::SetProperty("graphics.display.kernel_idle_timer.enabled"s,
                              timeout > std::chrono::milliseconds::zero() ? "true"s : "false"s);
            break;
    }
}

auto DisplayModeController::getKernelIdleTimerState(PhysicalDisplayId displayId) const
        -> KernelIdleTimerState {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr =
            FTL_EXPECT(mDisplays.get(displayId).ok_or(KernelIdleTimerState())).get();

    const auto desiredModeIdOpt =
            (std::scoped_lock(displayPtr->desiredModeLock), displayPtr->desiredModeOpt)
                    .transform([](const display::DisplayModeRequest& request) {
                        return request.mode.modePtr->getId();
                    });

    return {desiredModeIdOpt, displayPtr->isKernelIdleTimerEnabled};
}

} // namespace android::display
+17 −0
Original line number Diff line number Diff line
@@ -97,6 +97,17 @@ public:
    void setActiveMode(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
            EXCLUDES(mDisplayLock);

    void updateKernelIdleTimer(PhysicalDisplayId) REQUIRES(kMainThreadContext)
            EXCLUDES(mDisplayLock);

    struct KernelIdleTimerState {
        std::optional<DisplayModeId> desiredModeIdOpt = std::nullopt;
        bool isEnabled = false;
    };

    KernelIdleTimerState getKernelIdleTimerState(PhysicalDisplayId) const
            REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);

private:
    struct Display {
        template <size_t N>
@@ -121,6 +132,8 @@ private:

        DisplayModeRequestOpt pendingModeOpt GUARDED_BY(kMainThreadContext);
        bool isModeSetPending GUARDED_BY(kMainThreadContext) = false;

        bool isKernelIdleTimerEnabled GUARDED_BY(kMainThreadContext) = false;
    };

    using DisplayPtr = std::unique_ptr<Display>;
@@ -128,6 +141,10 @@ private:
    void setActiveModeLocked(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
            REQUIRES(mDisplayLock);

    using KernelIdleTimerController = scheduler::RefreshRateSelector::KernelIdleTimerController;
    void updateKernelIdleTimer(PhysicalDisplayId, std::chrono::milliseconds timeout,
                               KernelIdleTimerController) REQUIRES(mDisplayLock);

    // Set once when initializing the DisplayModeController, which the HWComposer must outlive.
    HWComposer* mComposerPtr = nullptr;

+6 −73
Original line number Diff line number Diff line
@@ -205,8 +205,6 @@ using ui::Dataspace;
using ui::DisplayPrimaries;
using ui::RenderIntent;

using KernelIdleTimerController = scheduler::RefreshRateSelector::KernelIdleTimerController;

namespace hal = android::hardware::graphics::composer::hal;

namespace {
@@ -374,8 +372,6 @@ const String16 sCaptureBlackoutContent("android.permission.CAPTURE_BLACKOUT_CONT
const String16 sInternalSystemWindow("android.permission.INTERNAL_SYSTEM_WINDOW");
const String16 sWakeupSurfaceFlinger("android.permission.WAKEUP_SURFACE_FLINGER");

const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";

// ---------------------------------------------------------------------------
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -6932,7 +6928,7 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {

    // Update the overlay on the main thread to avoid race conditions with
    // RefreshRateSelector::getActiveMode
    static_cast<void>(mScheduler->schedule([=, this] {
    static_cast<void>(mScheduler->schedule([=, this]() FTL_FAKE_GUARD(kMainThreadContext) {
        const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
        if (!display) {
            ALOGW("%s: default display is null", __func__);
@@ -6940,15 +6936,9 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {
        }
        if (!display->isRefreshRateOverlayEnabled()) return;

        const auto desiredModeIdOpt =
                mDisplayModeController.getDesiredMode(display->getPhysicalId())
                        .transform([](const display::DisplayModeRequest& request) {
                            return request.mode.modePtr->getId();
                        });

        const bool timerExpired = mKernelIdleTimerEnabled && expired;
        const auto state = mDisplayModeController.getKernelIdleTimerState(display->getPhysicalId());

        if (display->onKernelTimerChanged(desiredModeIdOpt, timerExpired)) {
        if (display->onKernelTimerChanged(state.desiredModeIdOpt, state.isEnabled && expired)) {
            mScheduler->scheduleFrame();
        }
    }));
@@ -6970,8 +6960,8 @@ void SurfaceFlinger::vrrDisplayIdle(bool idle) {
    }));
}

std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds>
SurfaceFlinger::getKernelIdleTimerProperties(PhysicalDisplayId displayId) {
auto SurfaceFlinger::getKernelIdleTimerProperties(PhysicalDisplayId displayId)
        -> std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds> {
    const bool isKernelIdleTimerHwcSupported = getHwComposer().getComposer()->isSupported(
            android::Hwc2::Composer::OptionalFeature::KernelIdleTimer);
    const auto timeout = getIdleTimerTimeout(displayId);
@@ -6995,63 +6985,6 @@ SurfaceFlinger::getKernelIdleTimerProperties(PhysicalDisplayId displayId) {
    return {std::nullopt, timeout};
}

void SurfaceFlinger::updateKernelIdleTimer(std::chrono::milliseconds timeout,
                                           KernelIdleTimerController controller,
                                           PhysicalDisplayId displayId) {
    switch (controller) {
        case KernelIdleTimerController::HwcApi: {
            getHwComposer().setIdleTimerEnabled(displayId, timeout);
            break;
        }
        case KernelIdleTimerController::Sysprop: {
            base::SetProperty(KERNEL_IDLE_TIMER_PROP, timeout > 0ms ? "true" : "false");
            break;
        }
    }
}

void SurfaceFlinger::toggleKernelIdleTimer() {
    using KernelIdleTimerAction = scheduler::RefreshRateSelector::KernelIdleTimerAction;

    const auto display = getDefaultDisplayDeviceLocked();
    if (!display) {
        ALOGW("%s: default display is null", __func__);
        return;
    }

    // If the support for kernel idle timer is disabled for the active display,
    // don't do anything.
    const std::optional<KernelIdleTimerController> kernelIdleTimerController =
            display->refreshRateSelector().kernelIdleTimerController();
    if (!kernelIdleTimerController.has_value()) {
        return;
    }

    const KernelIdleTimerAction action = display->refreshRateSelector().getIdleTimerAction();

    switch (action) {
        case KernelIdleTimerAction::TurnOff:
            if (mKernelIdleTimerEnabled) {
                SFTRACE_INT("KernelIdleTimer", 0);
                std::chrono::milliseconds constexpr kTimerDisabledTimeout = 0ms;
                updateKernelIdleTimer(kTimerDisabledTimeout, kernelIdleTimerController.value(),
                                      display->getPhysicalId());
                mKernelIdleTimerEnabled = false;
            }
            break;
        case KernelIdleTimerAction::TurnOn:
            if (!mKernelIdleTimerEnabled) {
                SFTRACE_INT("KernelIdleTimer", 1);
                const std::chrono::milliseconds timeout =
                        display->refreshRateSelector().getIdleTimerTimeout();
                updateKernelIdleTimer(timeout, kernelIdleTimerController.value(),
                                      display->getPhysicalId());
                mKernelIdleTimerEnabled = true;
            }
            break;
    }
}

// A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
class WindowDisconnector {
public:
@@ -7938,7 +7871,7 @@ status_t SurfaceFlinger::applyRefreshRateSelectorPolicy(

    if (const bool isPacesetter =
                mScheduler->onDisplayModeChanged(displayId, selector.getActiveMode())) {
        toggleKernelIdleTimer();
        mDisplayModeController.updateKernelIdleTimer(displayId);
    }

    auto preferredModeOpt = getPreferredDisplayMode(displayId, currentPolicy.defaultMode);
+1 −10
Original line number Diff line number Diff line
@@ -707,22 +707,13 @@ private:
    // ICEPowerCallback overrides:
    void notifyCpuLoadUp() override;

    // Toggles the kernel idle timer on or off depending the policy decisions around refresh rates.
    void toggleKernelIdleTimer() REQUIRES(mStateLock);

    using KernelIdleTimerController = scheduler::RefreshRateSelector::KernelIdleTimerController;

    // Get the controller and timeout that will help decide how the kernel idle timer will be
    // configured and what value to use as the timeout.
    std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds>
            getKernelIdleTimerProperties(PhysicalDisplayId) REQUIRES(mStateLock);
    // Updates the kernel idle timer either through HWC or through sysprop
    // depending on which controller is provided
    void updateKernelIdleTimer(std::chrono::milliseconds timeoutMs, KernelIdleTimerController,
                               PhysicalDisplayId) REQUIRES(mStateLock);
    // Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
    // make calls to sys prop each time.
    bool mKernelIdleTimerEnabled = false;

    // Show spinner with refresh rate overlay
    bool mRefreshRateOverlaySpinner = false;
    // Show render rate with refresh rate overlay