blob: f3fa9f6836d5de82b850f064173faf697c144c26 [file] [log] [blame]
/*
* Copyright (C) 2024 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.
*/
#include <aidl/android/hardware/power/CpuHeadroomParams.h>
#include <aidl/android/hardware/power/GpuHeadroomParams.h>
#include <aidl/android/os/CpuHeadroomParamsInternal.h>
#include <aidl/android/os/GpuHeadroomParamsInternal.h>
#include <aidl/android/os/IHintManager.h>
#include <android/binder_manager.h>
#include <android/system_health.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
using namespace android;
using namespace aidl::android::os;
namespace hal = aidl::android::hardware::power;
struct ACpuHeadroomParams : public CpuHeadroomParamsInternal {};
struct AGpuHeadroomParams : public GpuHeadroomParamsInternal {};
const int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50;
const int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000;
const int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50;
const int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000;
const int CPU_HEADROOM_MAX_TID_COUNT = 5;
struct ASystemHealthManager {
public:
static ASystemHealthManager* getInstance();
ASystemHealthManager(std::shared_ptr<IHintManager>& hintManager);
ASystemHealthManager() = delete;
~ASystemHealthManager();
int getCpuHeadroom(const ACpuHeadroomParams* params, float* outHeadroom);
int getGpuHeadroom(const AGpuHeadroomParams* params, float* outHeadroom);
int getCpuHeadroomMinIntervalMillis(int64_t* outMinIntervalMillis);
int getGpuHeadroomMinIntervalMillis(int64_t* outMinIntervalMillis);
private:
static ASystemHealthManager* create(std::shared_ptr<IHintManager> hintManager);
std::shared_ptr<IHintManager> mHintManager;
};
ASystemHealthManager* ASystemHealthManager::getInstance() {
static std::once_flag creationFlag;
static ASystemHealthManager* instance = nullptr;
std::call_once(creationFlag, []() { instance = create(nullptr); });
return instance;
}
ASystemHealthManager::ASystemHealthManager(std::shared_ptr<IHintManager>& hintManager)
: mHintManager(std::move(hintManager)) {}
ASystemHealthManager::~ASystemHealthManager() {}
ASystemHealthManager* ASystemHealthManager::create(std::shared_ptr<IHintManager> hintManager) {
if (!hintManager) {
hintManager = IHintManager::fromBinder(
ndk::SpAIBinder(AServiceManager_waitForService("performance_hint")));
}
if (hintManager == nullptr) {
ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
return nullptr;
}
return new ASystemHealthManager(hintManager);
}
ASystemHealthManager* ASystemHealth_acquireManager() {
return ASystemHealthManager::getInstance();
}
int ASystemHealthManager::getCpuHeadroom(const ACpuHeadroomParams* params, float* outHeadroom) {
std::optional<hal::CpuHeadroomResult> res;
::ndk::ScopedAStatus ret;
CpuHeadroomParamsInternal internalParams;
if (!params) {
ret = mHintManager->getCpuHeadroom(internalParams, &res);
} else {
ret = mHintManager->getCpuHeadroom(*params, &res);
}
if (!ret.isOk()) {
LOG_ALWAYS_FATAL_IF(ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT,
"Invalid ACpuHeadroomParams: %s", ret.getMessage());
ALOGE("ASystemHealth_getCpuHeadroom fails: %s", ret.getMessage());
if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
return ENOTSUP;
} else if (ret.getExceptionCode() == EX_SECURITY) {
return EPERM;
}
return EPIPE;
}
*outHeadroom = res->get<hal::CpuHeadroomResult::Tag::globalHeadroom>();
return OK;
}
int ASystemHealthManager::getGpuHeadroom(const AGpuHeadroomParams* params, float* outHeadroom) {
std::optional<hal::GpuHeadroomResult> res;
::ndk::ScopedAStatus ret;
GpuHeadroomParamsInternal internalParams;
if (!params) {
ret = mHintManager->getGpuHeadroom(internalParams, &res);
} else {
ret = mHintManager->getGpuHeadroom(*params, &res);
}
if (!ret.isOk()) {
LOG_ALWAYS_FATAL_IF(ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT,
"Invalid AGpuHeadroomParams: %s", ret.getMessage());
ALOGE("ASystemHealth_getGpuHeadroom fails: %s", ret.getMessage());
if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
return ENOTSUP;
}
return EPIPE;
}
*outHeadroom = res->get<hal::GpuHeadroomResult::Tag::globalHeadroom>();
return OK;
}
int ASystemHealthManager::getCpuHeadroomMinIntervalMillis(int64_t* outMinIntervalMillis) {
int64_t minIntervalMillis = 0;
::ndk::ScopedAStatus ret = mHintManager->getCpuHeadroomMinIntervalMillis(&minIntervalMillis);
if (!ret.isOk()) {
ALOGE("ASystemHealth_getCpuHeadroomMinIntervalMillis fails: %s", ret.getMessage());
if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
return ENOTSUP;
}
return EPIPE;
}
*outMinIntervalMillis = minIntervalMillis;
return OK;
}
int ASystemHealthManager::getGpuHeadroomMinIntervalMillis(int64_t* outMinIntervalMillis) {
int64_t minIntervalMillis = 0;
::ndk::ScopedAStatus ret = mHintManager->getGpuHeadroomMinIntervalMillis(&minIntervalMillis);
if (!ret.isOk()) {
ALOGE("ASystemHealth_getGpuHeadroomMinIntervalMillis fails: %s", ret.getMessage());
if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
return ENOTSUP;
}
return EPIPE;
}
*outMinIntervalMillis = minIntervalMillis;
return OK;
}
int ASystemHealth_getCpuHeadroom(const ACpuHeadroomParams* _Nullable params,
float* _Nonnull outHeadroom) {
LOG_ALWAYS_FATAL_IF(outHeadroom == nullptr, "%s: outHeadroom should not be null", __FUNCTION__);
auto manager = ASystemHealthManager::getInstance();
if (manager == nullptr) return ENOTSUP;
return manager->getCpuHeadroom(params, outHeadroom);
}
int ASystemHealth_getGpuHeadroom(const AGpuHeadroomParams* _Nullable params,
float* _Nonnull outHeadroom) {
LOG_ALWAYS_FATAL_IF(outHeadroom == nullptr, "%s: outHeadroom should not be null", __FUNCTION__);
auto manager = ASystemHealthManager::getInstance();
if (manager == nullptr) return ENOTSUP;
return manager->getGpuHeadroom(params, outHeadroom);
}
int ASystemHealth_getCpuHeadroomMinIntervalMillis(int64_t* _Nonnull outMinIntervalMillis) {
LOG_ALWAYS_FATAL_IF(outMinIntervalMillis == nullptr,
"%s: outMinIntervalMillis should not be null", __FUNCTION__);
auto manager = ASystemHealthManager::getInstance();
if (manager == nullptr) return ENOTSUP;
return manager->getCpuHeadroomMinIntervalMillis(outMinIntervalMillis);
}
int ASystemHealth_getGpuHeadroomMinIntervalMillis(int64_t* _Nonnull outMinIntervalMillis) {
LOG_ALWAYS_FATAL_IF(outMinIntervalMillis == nullptr,
"%s: outMinIntervalMillis should not be null", __FUNCTION__);
auto manager = ASystemHealthManager::getInstance();
if (manager == nullptr) return ENOTSUP;
return manager->getGpuHeadroomMinIntervalMillis(outMinIntervalMillis);
}
void ACpuHeadroomParams_setCalculationWindowMillis(ACpuHeadroomParams* _Nonnull params,
int windowMillis) {
LOG_ALWAYS_FATAL_IF(windowMillis < CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN ||
windowMillis > CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX,
"%s: windowMillis should be in range [50, 10000] but got %d", __FUNCTION__,
windowMillis);
params->calculationWindowMillis = windowMillis;
}
void AGpuHeadroomParams_setCalculationWindowMillis(AGpuHeadroomParams* _Nonnull params,
int windowMillis) {
LOG_ALWAYS_FATAL_IF(windowMillis < GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN ||
windowMillis > GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX,
"%s: windowMillis should be in range [50, 10000] but got %d", __FUNCTION__,
windowMillis);
params->calculationWindowMillis = windowMillis;
}
int ACpuHeadroomParams_getCalculationWindowMillis(ACpuHeadroomParams* _Nonnull params) {
return params->calculationWindowMillis;
}
int AGpuHeadroomParams_getCalculationWindowMillis(AGpuHeadroomParams* _Nonnull params) {
return params->calculationWindowMillis;
}
void ACpuHeadroomParams_setTids(ACpuHeadroomParams* _Nonnull params, const int* _Nonnull tids,
int tidsSize) {
LOG_ALWAYS_FATAL_IF(tids == nullptr, "%s: tids should not be null", __FUNCTION__);
LOG_ALWAYS_FATAL_IF(tidsSize > CPU_HEADROOM_MAX_TID_COUNT, "%s: tids size should not exceed 5",
__FUNCTION__);
params->tids.resize(tidsSize);
params->tids.clear();
for (int i = 0; i < tidsSize; ++i) {
LOG_ALWAYS_FATAL_IF(tids[i] <= 0, "ACpuHeadroomParams_setTids: Invalid non-positive tid %d",
tids[i]);
params->tids[i] = tids[i];
}
}
void ACpuHeadroomParams_setCalculationType(ACpuHeadroomParams* _Nonnull params,
ACpuHeadroomCalculationType calculationType) {
LOG_ALWAYS_FATAL_IF(calculationType < ACpuHeadroomCalculationType::
ACPU_HEADROOM_CALCULATION_TYPE_MIN ||
calculationType > ACpuHeadroomCalculationType::
ACPU_HEADROOM_CALCULATION_TYPE_AVERAGE,
"%s: calculationType should be one of ACpuHeadroomCalculationType values "
"but got %d",
__FUNCTION__, calculationType);
params->calculationType = static_cast<hal::CpuHeadroomParams::CalculationType>(calculationType);
}
ACpuHeadroomCalculationType ACpuHeadroomParams_getCalculationType(
ACpuHeadroomParams* _Nonnull params) {
return static_cast<ACpuHeadroomCalculationType>(params->calculationType);
}
void AGpuHeadroomParams_setCalculationType(AGpuHeadroomParams* _Nonnull params,
AGpuHeadroomCalculationType calculationType) {
LOG_ALWAYS_FATAL_IF(calculationType < AGpuHeadroomCalculationType::
AGPU_HEADROOM_CALCULATION_TYPE_MIN ||
calculationType > AGpuHeadroomCalculationType::
AGPU_HEADROOM_CALCULATION_TYPE_AVERAGE,
"%s: calculationType should be one of AGpuHeadroomCalculationType values "
"but got %d",
__FUNCTION__, calculationType);
params->calculationType = static_cast<hal::GpuHeadroomParams::CalculationType>(calculationType);
}
AGpuHeadroomCalculationType AGpuHeadroomParams_getCalculationType(
AGpuHeadroomParams* _Nonnull params) {
return static_cast<AGpuHeadroomCalculationType>(params->calculationType);
}
ACpuHeadroomParams* _Nonnull ACpuHeadroomParams_create() {
return new ACpuHeadroomParams();
}
AGpuHeadroomParams* _Nonnull AGpuHeadroomParams_create() {
return new AGpuHeadroomParams();
}
void ACpuHeadroomParams_destroy(ACpuHeadroomParams* _Nonnull params) {
delete params;
}
void AGpuHeadroomParams_destroy(AGpuHeadroomParams* _Nonnull params) {
delete params;
}