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

Commit a3099857 authored by Peiyong Lin's avatar Peiyong Lin Committed by Android (Google) Code Review
Browse files

Merge "Add new PowerAdvisor interface for SF to pass hints to the power HAL."

parents bb0ddf53 5d22d4ff
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ cc_defaults {
        "android.hardware.graphics.composer@2.2",
        "android.hardware.graphics.composer@2.3",
        "android.hardware.power@1.0",
        "android.hardware.power@1.3",
        "libbase",
        "libbinder",
        "libbufferhubqueue",
@@ -71,6 +72,7 @@ cc_defaults {
        "android.hardware.graphics.composer@2.1",
        "android.hardware.graphics.composer@2.2",
        "android.hardware.graphics.composer@2.3",
        "android.hardware.power@1.3",
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
@@ -99,6 +101,7 @@ filegroup {
        "DisplayHardware/HWC2.cpp",
        "DisplayHardware/HWComposer.cpp",
        "DisplayHardware/HWComposerBufferCache.cpp",
        "DisplayHardware/PowerAdvisor.cpp",
        "DisplayHardware/VirtualDisplaySurface.cpp",
        "DispSync.cpp",
        "Effects/Daltonizer.cpp",
+10 −3
Original line number Diff line number Diff line
@@ -144,7 +144,7 @@ Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
    }

    auto display = std::make_unique<Display>(
            *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
            *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, DisplayType::Virtual);
    display->setConnected(true);
    *outDisplay = display.get();
    mDisplays.emplace(displayId, std::move(display));
@@ -183,7 +183,7 @@ void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
        }

        auto newDisplay = std::make_unique<Display>(
                *mComposer.get(), mCapabilities, displayId, displayType);
                *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, displayType);
        newDisplay->setConnected(true);
        mDisplays.emplace(displayId, std::move(newDisplay));
    } else if (connection == Connection::Disconnected) {
@@ -225,10 +225,11 @@ Error Device::flushCommands()

// Display methods

Display::Display(android::Hwc2::Composer& composer,
Display::Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
                 const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
                 DisplayType type)
      : mComposer(composer),
        mPowerAdvisor(advisor),
        mCapabilities(capabilities),
        mId(id),
        mIsConnected(false),
@@ -611,6 +612,12 @@ Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,

Error Display::setColorMode(ColorMode mode, RenderIntent renderIntent)
{
    // When the color mode is switched to DISPLAY_P3, we want to boost the GPU frequency
    // so that GPU composition can finish in time. When color mode is switched from
    // DISPLAY_P3, we want to reset GPU frequency.
    const bool expensiveRenderingExpected = (mode == ColorMode::DISPLAY_P3);
    mPowerAdvisor.setExpensiveRenderingExpected(mId, expensiveRenderingExpected);

    auto intError = mComposer.setColorMode(mId, mode, renderIntent);
    return static_cast<Error>(intError);
}
+6 −1
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@
#include <unordered_set>
#include <vector>

#include "PowerAdvisor.h"

namespace android {
    class Fence;
    class FloatRect;
@@ -122,6 +124,7 @@ private:
    std::unique_ptr<android::Hwc2::Composer> mComposer;
    std::unordered_set<Capability> mCapabilities;
    std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
    android::Hwc2::impl::PowerAdvisor mPowerAdvisor;
    bool mRegisteredCallback = false;
};

@@ -129,7 +132,8 @@ private:
class Display
{
public:
    Display(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
    Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
            const std::unordered_set<Capability>& capabilities,
            hwc2_display_t id, DisplayType type);
    ~Display();

@@ -285,6 +289,7 @@ private:
    // this HWC2::Display, so these references are guaranteed to be valid for
    // the lifetime of this object.
    android::Hwc2::Composer& mComposer;
    android::Hwc2::PowerAdvisor& mPowerAdvisor;
    const std::unordered_set<Capability>& mCapabilities;

    hwc2_display_t mId;
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#undef LOG_TAG
#define LOG_TAG "PowerAdvisor"

#include <cinttypes>

#include <utils/Log.h>
#include <utils/Mutex.h>

#include "PowerAdvisor.h"

namespace android {
namespace Hwc2 {

PowerAdvisor::~PowerAdvisor() = default;

namespace impl {

namespace V1_0 = android::hardware::power::V1_0;
using V1_3::PowerHint;

PowerAdvisor::~PowerAdvisor() = default;

PowerAdvisor::PowerAdvisor() = default;

void PowerAdvisor::setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) {
    if (expected) {
        mExpensiveDisplays.insert(displayId);
    } else {
        mExpensiveDisplays.erase(displayId);
    }

    const sp<V1_3::IPower> powerHal = getPowerHal();
    if (powerHal == nullptr) {
        return;
    }

    const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
    if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
        auto ret = powerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING,
                                                expectsExpensiveRendering);
        // If Power HAL 1.3 was available previously but now fails,
        // it may restart, so attempt to reconnect next time
        if (!ret.isOk()) {
            mReconnectPowerHal = true;
            return;
        }
        mNotifiedExpensiveRendering = expectsExpensiveRendering;
    }
}

sp<V1_3::IPower> PowerAdvisor::getPowerHal() {
    static sp<V1_3::IPower> sPowerHal_1_3 = nullptr;
    static bool sHasPowerHal_1_3 = true;

    if (mReconnectPowerHal) {
        sPowerHal_1_3 = nullptr;
        mReconnectPowerHal = false;
    }

    // Power HAL 1.3 is not guaranteed to be available, thus we need to query
    // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
    // Power HAL 1.0 is always available, thus if we fail to query it, it means
    // Power HAL is not available temporarily and we should retry later. However,
    // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3,
    // it means Power HAL 1.3 is not available at all, so we should stop trying.
    if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) {
        sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
        if (powerHal_1_0 != nullptr) {
            // Try to cast to Power HAL 1.3
            sPowerHal_1_3 =  V1_3::IPower::castFrom(powerHal_1_0);
            if (sPowerHal_1_3 == nullptr) {
                ALOGW("No Power HAL 1.3 service in system");
                sHasPowerHal_1_3 = false;
            } else {
                ALOGI("Loaded Power HAL 1.3 service");
            }
        }
    }
    return sPowerHal_1_3;
}

} // namespace impl
} // namespace Hwc2
} // namespace android
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
#include <hardware/hwcomposer2.h>
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11

#include <android/hardware/power/1.3/IPower.h>
#include <utils/StrongPointer.h>

#include <unordered_set>

namespace android {
namespace Hwc2 {

class PowerAdvisor {
public:
    virtual ~PowerAdvisor();

    virtual void setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) = 0;
};

namespace impl {

namespace V1_3 = android::hardware::power::V1_3;

// PowerAdvisor is a wrapper around IPower HAL which takes into account the
// full state of the system when sending out power hints to things like the GPU.
class PowerAdvisor final : public Hwc2::PowerAdvisor {
public:
    PowerAdvisor();
    ~PowerAdvisor() override;

    void setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) override;

private:
    sp<V1_3::IPower> getPowerHal();

    std::unordered_set<hwc2_display_t> mExpensiveDisplays;
    bool mNotifiedExpensiveRendering = false;
    bool mReconnectPowerHal = false;
};

} // namespace impl
} // namespace Hwc2
} // namespace android
Loading