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

Commit 00a764ee authored by Dennis Kiilerich's avatar Dennis Kiilerich
Browse files

Use power mode of all independent displays to control power optimisations.

In the following cases, if there is any performance-optimised/independent active display (powered on) then power optimisations are disabled. If there is no performance-optimised/independent active display then power optimisations are enabled, even if there are power-optimised displays that are powered on.
* Physical or virtual display power mode change
* Physical or virtual display added or removed

Power optimisations include:
* Lowering thread priority

Bug: 342681202
Bug: 241285876

Flag: android.companion.virtualdevice.flags.correct_virtual_display_power_state

Test: manually tested with flag on/off using Android Auto Projected

Change-Id: I96068c8779dbfe2b51b4d9acd522b6cb3995681f
parent d0503fa4
Loading
Loading
Loading
Loading
+82 −13
Original line number Diff line number Diff line
@@ -4075,6 +4075,10 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
        incRefreshableDisplays();
    }

    if (FlagManager::getInstance().correct_virtual_display_power_state()) {
        applyOptimizationPolicy(__func__);
    }

    mDisplays.try_emplace(displayToken, std::move(display));

    // For an external display, loadDisplayModes already attempted to select the same mode
@@ -4131,6 +4135,10 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) {
            // not be accessible.
        }));
    }

    if (FlagManager::getInstance().correct_virtual_display_power_state()) {
        applyOptimizationPolicy(__func__);
    }
}

void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,
@@ -5679,7 +5687,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
    }

    const auto displayId = display->getPhysicalId();
    ALOGD("Setting power mode %d on display %s", mode, to_string(displayId).c_str());
    ALOGD("Setting power mode %d on physical display %s", mode, to_string(displayId).c_str());

    const auto currentMode = display->getPowerMode();
    if (currentMode == mode) {
@@ -5722,11 +5730,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
        }

        if (displayId == mActiveDisplayId) {
            // TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall
            // and set it before SCHED_FIFO due to b/190237315.
            constexpr const char* kWhence = "setPowerMode(ON)";
            setSchedAttr(true, kWhence);
            setSchedFifo(true, kWhence);
            if (FlagManager::getInstance().correct_virtual_display_power_state()) {
                applyOptimizationPolicy("setPhysicalDisplayPowerMode(ON)");
            } else {
                disablePowerOptimizations("setPhysicalDisplayPowerMode(ON)");
            }
        }

        getHwComposer().setPowerMode(displayId, mode);
@@ -5753,9 +5761,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
            if (const auto display = getActivatableDisplay()) {
                onActiveDisplayChangedLocked(activeDisplay.get(), *display);
            } else {
                constexpr const char* kWhence = "setPowerMode(OFF)";
                setSchedFifo(false, kWhence);
                setSchedAttr(false, kWhence);
                if (FlagManager::getInstance().correct_virtual_display_power_state()) {
                    applyOptimizationPolicy("setPhysicalDisplayPowerMode(OFF)");
                } else {
                    enablePowerOptimizations("setPhysicalDisplayPowerMode(OFF)");
                }

                if (currentModeNotDozeSuspend) {
                    if (!FlagManager::getInstance().multithreaded_present()) {
@@ -5816,7 +5826,67 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:

    mScheduler->setDisplayPowerMode(displayId, mode);

    ALOGD("Finished setting power mode %d on display %s", mode, to_string(displayId).c_str());
    ALOGD("Finished setting power mode %d on physical display %s", mode,
          to_string(displayId).c_str());
}

void SurfaceFlinger::setVirtualDisplayPowerMode(const sp<DisplayDevice>& display,
                                                hal::PowerMode mode) {
    if (!display->isVirtual()) {
        ALOGE("%s: Invalid operation on physical display", __func__);
        return;
    }

    const auto displayId = display->getVirtualId();
    ALOGD("Setting power mode %d on virtual display %s %s", mode, to_string(displayId).c_str(),
          display->getDisplayName().c_str());

    display->setPowerMode(static_cast<hal::PowerMode>(mode));

    applyOptimizationPolicy(__func__);

    ALOGD("Finished setting power mode %d on virtual display %s", mode,
          to_string(displayId).c_str());
}

bool SurfaceFlinger::shouldOptimizeForPerformance() {
    for (const auto& [_, display] : mDisplays) {
        // Displays that are optimized for power are always powered on and should not influence
        // whether there is an active display for the purpose of power optimization, etc. If these
        // displays are being shown somewhere, a different (physical or virtual) display that is
        // optimized for performance will be powered on in addition. Displays optimized for
        // performance will change power mode, so if they are off then they are not active.
        if (display->isPoweredOn() &&
            display->getOptimizationPolicy() ==
                    gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance) {
            return true;
        }
    }
    return false;
}

void SurfaceFlinger::enablePowerOptimizations(const char* whence) {
    ALOGD("%s: Enabling power optimizations", whence);

    setSchedAttr(false, whence);
    setSchedFifo(false, whence);
}

void SurfaceFlinger::disablePowerOptimizations(const char* whence) {
    ALOGD("%s: Disabling power optimizations", whence);

    // TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall
    // and set it before SCHED_FIFO due to b/190237315.
    setSchedAttr(true, whence);
    setSchedFifo(true, whence);
}

void SurfaceFlinger::applyOptimizationPolicy(const char* whence) {
    if (shouldOptimizeForPerformance()) {
        disablePowerOptimizations(whence);
    } else {
        enablePowerOptimizations(whence);
    }
}

void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
@@ -5838,9 +5908,8 @@ void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
            ALOGE("Failed to set power mode %d for display token %p", mode, displayToken.get());
        } else if (display->isVirtual()) {
            if (FlagManager::getInstance().correct_virtual_display_power_state()) {
                ALOGD("Setting power mode %d on virtual display %s", mode,
                      display->getDisplayName().c_str());
                display->setPowerMode(static_cast<hal::PowerMode>(mode));
                ftl::FakeGuard guard(mStateLock);
                setVirtualDisplayPowerMode(display, static_cast<hal::PowerMode>(mode));
            } else {
                ALOGW("Attempt to set power mode %d for virtual display", mode);
            }
+16 −0
Original line number Diff line number Diff line
@@ -735,6 +735,22 @@ private:
    // Called on the main thread in response to setPowerMode()
    void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)
            REQUIRES(mStateLock, kMainThreadContext);
    void setVirtualDisplayPowerMode(const sp<DisplayDevice>& display, hal::PowerMode mode)
            REQUIRES(mStateLock, kMainThreadContext);

    // Returns whether to optimize globally for performance instead of power.
    bool shouldOptimizeForPerformance() REQUIRES(mStateLock);

    // Turns on power optimizations, for example when there are no displays to be optimized for
    // performance.
    static void enablePowerOptimizations(const char* whence);

    // Turns off power optimizations.
    static void disablePowerOptimizations(const char* whence);

    // Enables or disables power optimizations depending on whether there are displays that should
    // be optimized for performance.
    void applyOptimizationPolicy(const char* whence) REQUIRES(mStateLock);

    // Returns the preferred mode for PhysicalDisplayId if the Scheduler has selected one for that
    // display. Falls back to the display's defaultModeId otherwise.