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

Commit e50205ba authored by Michael Wright's avatar Michael Wright Committed by android-build-merger
Browse files

Merge "Add new PowerAdvisor interface for SF to pass hints to the power HAL." into pi-dev

am: d98772df

Change-Id: Iad5c88cd15bdcbfada008d22d50262715d30175e
parents d337ebdb d98772df
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ cc_defaults {
        "android.hardware.graphics.composer@2.1",
        "android.hardware.graphics.composer@2.2",
        "android.hardware.power@1.0",
        "android.hardware.power@1.3",
        "libbase",
        "libbinder",
        "libbufferhubqueue",
@@ -69,6 +70,7 @@ cc_defaults {
        "android.hardware.graphics.allocator@2.0",
        "android.hardware.graphics.composer@2.1",
        "android.hardware.graphics.composer@2.2",
        "android.hardware.power@1.3",
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
@@ -96,6 +98,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
@@ -138,7 +138,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));
@@ -177,7 +177,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) {
@@ -219,10 +219,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),
@@ -605,6 +606,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;
@@ -119,6 +121,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;
};

@@ -126,7 +129,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();

@@ -282,6 +286,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