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

Commit 12375902 authored by Lais Andrade's avatar Lais Andrade
Browse files

Use PowerHalController in PowerManagerService

Bug: 150878220
Test: atest powermanager_test
Change-Id: Ifaac265c48f1ed10522b9e4e20fbf708357f51b4
parent 1b2d13ac
Loading
Loading
Loading
Loading
+37 −260
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
#include "jni.h"

#include <nativehelper/ScopedUtfChars.h>
#include <powermanager/PowerHalController.h>
#include <powermanager/PowerHalLoader.h>

#include <limits.h>

@@ -46,8 +48,6 @@

#include "com_android_server_power_PowerManagerService.h"

using android::hardware::Return;
using android::hardware::Void;
using android::hardware::power::Boost;
using android::hardware::power::Mode;
using android::hardware::power::V1_0::PowerHint;
@@ -72,18 +72,7 @@ static struct {
// ----------------------------------------------------------------------------

static jobject gPowerManagerServiceObj;
static sp<IPowerV1_0> gPowerHalHidlV1_0_ = nullptr;
static sp<IPowerV1_1> gPowerHalHidlV1_1_ = nullptr;
static sp<IPowerAidl> gPowerHalAidl_ = nullptr;
static std::mutex gPowerHalMutex;

enum class HalVersion {
    NONE,
    HIDL_1_0,
    HIDL_1_1,
    AIDL,
};

static PowerHalController gPowerHalController;
static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];

// Throttling interval for user activity calls.
@@ -101,206 +90,36 @@ static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodNa
    return false;
}

// Check validity of current handle to the power HAL service, and connect to it if necessary.
// The caller must be holding gPowerHalMutex.
static HalVersion connectPowerHalLocked() {
    static bool gPowerHalHidlExists = true;
    static bool gPowerHalAidlExists = true;
    if (!gPowerHalHidlExists && !gPowerHalAidlExists) {
        return HalVersion::NONE;
    }
    if (gPowerHalAidlExists) {
        if (!gPowerHalAidl_) {
            gPowerHalAidl_ = waitForVintfService<IPowerAidl>();
        }
        if (gPowerHalAidl_) {
            ALOGV("Successfully connected to Power HAL AIDL service.");
            return HalVersion::AIDL;
        } else {
            gPowerHalAidlExists = false;
        }
    }
    if (gPowerHalHidlExists && gPowerHalHidlV1_0_ == nullptr) {
        gPowerHalHidlV1_0_ = IPowerV1_0::getService();
        if (gPowerHalHidlV1_0_) {
            ALOGV("Successfully connected to Power HAL HIDL 1.0 service.");
            // Try cast to powerHAL HIDL V1_1
            gPowerHalHidlV1_1_ = IPowerV1_1::castFrom(gPowerHalHidlV1_0_);
            if (gPowerHalHidlV1_1_) {
                ALOGV("Successfully connected to Power HAL HIDL 1.1 service.");
            }
        } else {
            ALOGV("Couldn't load power HAL HIDL service");
            gPowerHalHidlExists = false;
            return HalVersion::NONE;
        }
    }
    if (gPowerHalHidlV1_1_) {
        return HalVersion::HIDL_1_1;
    } else if (gPowerHalHidlV1_0_) {
        return HalVersion::HIDL_1_0;
    }
    return HalVersion::NONE;
}

// Check if a call to a power HAL function failed; if so, log the failure and invalidate the
// current handle to the power HAL service.
bool processPowerHalReturn(bool isOk, const char* functionName) {
    if (!isOk) {
        ALOGE("%s() failed: power HAL service not available.", functionName);
        gPowerHalMutex.lock();
        gPowerHalHidlV1_0_ = nullptr;
        gPowerHalHidlV1_1_ = nullptr;
        gPowerHalAidl_ = nullptr;
        gPowerHalMutex.unlock();
    }
    return isOk;
}

enum class HalSupport {
    UNKNOWN = 0,
    ON,
    OFF,
};

static void setPowerBoostWithHandle(sp<IPowerAidl> handle, Boost boost, int32_t durationMs) {
    // Android framework only sends boost upto DISPLAY_UPDATE_IMMINENT.
    // Need to increase the array size if more boost supported.
    static std::array<std::atomic<HalSupport>,
                      static_cast<int32_t>(Boost::DISPLAY_UPDATE_IMMINENT) + 1>
            boostSupportedArray = {HalSupport::UNKNOWN};

    // Quick return if boost is not supported by HAL
    if (boost > Boost::DISPLAY_UPDATE_IMMINENT ||
        boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::OFF) {
        ALOGV("Skipped setPowerBoost %s because HAL doesn't support it", toString(boost).c_str());
        return;
    }

    if (boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::UNKNOWN) {
        bool isSupported = false;
        handle->isBoostSupported(boost, &isSupported);
        boostSupportedArray[static_cast<int32_t>(boost)] =
            isSupported ? HalSupport::ON : HalSupport::OFF;
        if (!isSupported) {
            ALOGV("Skipped setPowerBoost %s because HAL doesn't support it",
                  toString(boost).c_str());
            return;
        }
    }

    auto ret = handle->setBoost(boost, durationMs);
    processPowerHalReturn(ret.isOk(), "setPowerBoost");
    SurfaceComposerClient::notifyPowerBoost(static_cast<int32_t>(boost));
}

static void setPowerBoost(Boost boost, int32_t durationMs) {
    std::unique_lock<std::mutex> lock(gPowerHalMutex);
    if (connectPowerHalLocked() != HalVersion::AIDL) {
        ALOGV("Power HAL AIDL not available");
        return;
    }
    sp<IPowerAidl> handle = gPowerHalAidl_;
    lock.unlock();
    setPowerBoostWithHandle(handle, boost, durationMs);
}

static bool setPowerModeWithHandle(sp<IPowerAidl> handle, Mode mode, bool enabled) {
    // Android framework only sends mode upto DISPLAY_INACTIVE.
    // Need to increase the array if more mode supported.
    static std::array<std::atomic<HalSupport>, static_cast<int32_t>(Mode::DISPLAY_INACTIVE) + 1>
            modeSupportedArray = {HalSupport::UNKNOWN};

    // Quick return if mode is not supported by HAL
    if (mode > Mode::DISPLAY_INACTIVE ||
        modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::OFF) {
        ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
        return false;
    }

    if (modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::UNKNOWN) {
        bool isSupported = false;
        handle->isModeSupported(mode, &isSupported);
        modeSupportedArray[static_cast<int32_t>(mode)] =
            isSupported ? HalSupport::ON : HalSupport::OFF;
        if (!isSupported) {
            ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
            return false;
        }
    }

    auto ret = handle->setMode(mode, enabled);
    processPowerHalReturn(ret.isOk(), "setPowerMode");
    return ret.isOk();
    gPowerHalController.setBoost(boost, durationMs);
    SurfaceComposerClient::notifyPowerBoost(static_cast<int32_t>(boost));
}

static bool setPowerMode(Mode mode, bool enabled) {
    std::unique_lock<std::mutex> lock(gPowerHalMutex);
    if (connectPowerHalLocked() != HalVersion::AIDL) {
        ALOGV("Power HAL AIDL not available");
        return false;
    }
    sp<IPowerAidl> handle = gPowerHalAidl_;
    lock.unlock();
    return setPowerModeWithHandle(handle, mode, enabled);
    auto result = gPowerHalController.setMode(mode, enabled);
    return result == PowerHalResult::SUCCESSFUL;
}

static void sendPowerHint(PowerHint hintId, uint32_t data) {
    std::unique_lock<std::mutex> lock(gPowerHalMutex);
    switch (connectPowerHalLocked()) {
        case HalVersion::NONE:
            return;
        case HalVersion::HIDL_1_0: {
            sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
            lock.unlock();
            auto ret = handle->powerHint(hintId, data);
            processPowerHalReturn(ret.isOk(), "powerHint");
            break;
        }
        case HalVersion::HIDL_1_1: {
            sp<IPowerV1_1> handle = gPowerHalHidlV1_1_;
            lock.unlock();
            auto ret = handle->powerHintAsync(hintId, data);
            processPowerHalReturn(ret.isOk(), "powerHintAsync");
            break;
        }
        case HalVersion::AIDL: {
            if (hintId == PowerHint::INTERACTION) {
                sp<IPowerAidl> handle = gPowerHalAidl_;
                lock.unlock();
                setPowerBoostWithHandle(handle, Boost::INTERACTION, data);
    switch (hintId) {
        case PowerHint::INTERACTION:
            gPowerHalController.setBoost(Boost::INTERACTION, data);
            SurfaceComposerClient::notifyPowerBoost(static_cast<int32_t>(Boost::INTERACTION));
            break;
            } else if (hintId == PowerHint::LAUNCH) {
                sp<IPowerAidl> handle = gPowerHalAidl_;
                lock.unlock();
                setPowerModeWithHandle(handle, Mode::LAUNCH, static_cast<bool>(data));
        case PowerHint::LAUNCH:
            gPowerHalController.setMode(Mode::LAUNCH, static_cast<bool>(data));
            break;
            } else if (hintId == PowerHint::LOW_POWER) {
                sp<IPowerAidl> handle = gPowerHalAidl_;
                lock.unlock();
                setPowerModeWithHandle(handle, Mode::LOW_POWER, static_cast<bool>(data));
        case PowerHint::LOW_POWER:
            gPowerHalController.setMode(Mode::LOW_POWER, static_cast<bool>(data));
            break;
            } else if (hintId == PowerHint::SUSTAINED_PERFORMANCE) {
                sp<IPowerAidl> handle = gPowerHalAidl_;
                lock.unlock();
                setPowerModeWithHandle(handle, Mode::SUSTAINED_PERFORMANCE,
                                       static_cast<bool>(data));
        case PowerHint::SUSTAINED_PERFORMANCE:
            gPowerHalController.setMode(Mode::SUSTAINED_PERFORMANCE, static_cast<bool>(data));
            break;
            } else if (hintId == PowerHint::VR_MODE) {
                sp<IPowerAidl> handle = gPowerHalAidl_;
                lock.unlock();
                setPowerModeWithHandle(handle, Mode::VR, static_cast<bool>(data));
        case PowerHint::VR_MODE:
            gPowerHalController.setMode(Mode::VR, static_cast<bool>(data));
            break;
            } else {
        default:
            ALOGE("Unsupported power hint: %s.", toString(hintId).c_str());
                return;
            }
        }
        default: {
            ALOGE("Unknown power HAL state");
            return;
        }
    }
}

@@ -388,10 +207,7 @@ void disableAutoSuspend() {

static void nativeInit(JNIEnv* env, jobject obj) {
    gPowerManagerServiceObj = env->NewGlobalRef(obj);

    gPowerHalMutex.lock();
    connectPowerHalLocked();
    gPowerHalMutex.unlock();
    gPowerHalController.init();
}

static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
@@ -405,35 +221,12 @@ static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring
}

static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
    std::unique_lock<std::mutex> lock(gPowerHalMutex);
    switch (connectPowerHalLocked()) {
        case HalVersion::NONE:
            return;
        case HalVersion::HIDL_1_0:
            FALLTHROUGH_INTENDED;
        case HalVersion::HIDL_1_1: {
    android::base::Timer t;
            sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
            lock.unlock();
            auto ret = handle->setInteractive(enable);
            processPowerHalReturn(ret.isOk(), "setInteractive");
    gPowerHalController.setMode(Mode::INTERACTIVE, enable);
    if (t.duration() > 20ms) {
        ALOGD("Excessive delay in setInteractive(%s) while turning screen %s",
              enable ? "true" : "false", enable ? "on" : "off");
    }
            return;
        }
        case HalVersion::AIDL: {
            sp<IPowerAidl> handle = gPowerHalAidl_;
            lock.unlock();
            setPowerModeWithHandle(handle, Mode::INTERACTIVE, enable);
            return;
        }
        default: {
            ALOGE("Unknown power HAL state");
            return;
        }
    }
}

static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
@@ -467,29 +260,13 @@ static jboolean nativeSetPowerMode(JNIEnv* /* env */, jclass /* clazz */, jint m
}

static void nativeSetFeature(JNIEnv* /* env */, jclass /* clazz */, jint featureId, jint data) {
    std::unique_lock<std::mutex> lock(gPowerHalMutex);
    switch (connectPowerHalLocked()) {
        case HalVersion::NONE:
            return;
        case HalVersion::HIDL_1_0:
            FALLTHROUGH_INTENDED;
        case HalVersion::HIDL_1_1: {
            sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
            lock.unlock();
            auto ret = handle->setFeature(static_cast<Feature>(featureId), static_cast<bool>(data));
            processPowerHalReturn(ret.isOk(), "setFeature");
            return;
        }
        case HalVersion::AIDL: {
            sp<IPowerAidl> handle = gPowerHalAidl_;
            lock.unlock();
            setPowerModeWithHandle(handle, Mode::DOUBLE_TAP_TO_WAKE, static_cast<bool>(data));
            return;
        }
        default: {
            ALOGE("Unknown power HAL state");
            return;
        }
    Feature feature = static_cast<Feature>(featureId);
    switch (feature) {
        case Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
            gPowerHalController.setMode(Mode::DOUBLE_TAP_TO_WAKE, static_cast<bool>(data));
            break;
        default:
            ALOGE("Unsupported feature: %s.", toString(feature).c_str());
    }
}