* Copyright (c) 2022-2025 Huawei Device Co., Ltd.
* 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 "efficiency_resources_operation.h"
#include "singleton.h"
#include "common.h"
#include "background_task_manager.h"
#include "efficiency_resource_info.h"
#include "efficiency_resource_log.h"
#include "hitrace_meter.h"
namespace OHOS {
namespace BackgroundTaskMgr {
namespace {
static constexpr int32_t APPLY_EFFICIENCY_RESOURCES_PARAMS = 1;
}
struct AsyncCallbackInfoGetAllEfficiencyResources : public AsyncWorkData {
explicit AsyncCallbackInfoGetAllEfficiencyResources(napi_env env) : AsyncWorkData(env) {}
std::vector<std::shared_ptr<EfficiencyResourceInfo>> efficiencyResourceInfoList;
};
napi_value GetNamedBoolValue(const napi_env &env, napi_value &object, const char* utf8name,
bool& result, bool isNecessary)
{
bool hasNamedProperty = false;
napi_value boolValue = nullptr;
if (napi_has_named_property(env, object, utf8name, &hasNamedProperty) != napi_ok || !hasNamedProperty) {
if (isNecessary) {
BGTASK_LOGE("ParseParameters failed, %{public}s not exist, is nullptr", utf8name);
return nullptr;
} else {
return Common::NapiGetNull(env);
}
}
BGTASK_NAPI_CALL(env, napi_get_named_property(env, object, utf8name, &boolValue));
if (!Common::GetBooleanValue(env, boolValue, result)) {
BGTASK_LOGE("ParseParameters failed, %{public}s is nullptr", utf8name);
return nullptr;
}
BGTASK_LOGD("GetNamedBoolValue: %{public}s is %{public}d", utf8name, result);
return Common::NapiGetNull(env);
}
napi_value GetNamedInt32Value(const napi_env &env, napi_value &object, const char* utf8name,
int32_t& result, bool isNecessary = true)
{
bool hasNamedProperty = false;
napi_value intValue = nullptr;
if (napi_has_named_property(env, object, utf8name, &hasNamedProperty) != napi_ok || !hasNamedProperty) {
if (isNecessary) {
BGTASK_LOGE("ParseParameters failed, %{public}s not exist, is nullptr", utf8name);
return nullptr;
}
return Common::NapiGetNull(env);
}
BGTASK_NAPI_CALL(env, napi_get_named_property(env, object, utf8name, &intValue));
if (!Common::GetInt32NumberValue(env, intValue, result)) {
BGTASK_LOGE("ParseParameters failed, %{public}s is nullptr", utf8name);
return nullptr;
}
if (result < 0) {
BGTASK_LOGE("%{public}s can't be a negtive number: %{public}d", utf8name, result);
return nullptr;
}
BGTASK_LOGD("GetNamedInt32Value: %{public}s is %{public}d", utf8name, result);
return Common::NapiGetNull(env);
}
napi_value GetNamedStringValue(const napi_env &env, napi_value &object, std::string& result)
{
bool hasNamedProperty = false;
napi_value stringValue = nullptr;
if (napi_has_named_property(env, object, "reason", &hasNamedProperty) != napi_ok || !hasNamedProperty) {
BGTASK_LOGE("ParseParameters failed, reason not exist, is nullptr");
return nullptr;
}
BGTASK_NAPI_CALL(env, napi_get_named_property(env, object, "reason", &stringValue));
if (!Common::GetStringValue(env, stringValue, result)) {
BGTASK_LOGE("ParseParameters failed, reason is nullptr");
return nullptr;
}
BGTASK_LOGD("GetNamedStringValue: reason is %{public}s", result.c_str());
return Common::NapiGetNull(env);
}
napi_value ParseParameters(const napi_env &env, const napi_callback_info &info,
EfficiencyResourceInfo ¶ms, bool isThrow)
{
size_t argc = APPLY_EFFICIENCY_RESOURCES_PARAMS;
napi_value argv[APPLY_EFFICIENCY_RESOURCES_PARAMS] = {nullptr};
BGTASK_NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
if (argc != APPLY_EFFICIENCY_RESOURCES_PARAMS) {
Common::HandleParamErr(env, ERR_PARAM_NUMBER_ERR, isThrow);
return nullptr;
}
int32_t resourceNumber {0};
bool isApply {false};
int32_t timeOut {0};
std::string reason {""};
bool isPersist {false};
bool isProcess {false};
int32_t cpuLevel {static_cast<int32_t>(EfficiencyResourcesCpuLevel::DEFAULT)};
if (!GetNamedInt32Value(env, argv[0], "resourceTypes", resourceNumber)) {
Common::HandleParamErr(env, ERR_RESOURCE_TYPES_INVALID, isThrow);
return nullptr;
}
if (!GetNamedBoolValue(env, argv[0], "isApply", isApply, true)) {
Common::HandleParamErr(env, ERR_ISAPPLY_NULL_OR_TYPE_ERR, isThrow);
return nullptr;
}
if (!GetNamedInt32Value(env, argv[0], "timeOut", timeOut)) {
Common::HandleParamErr(env, ERR_TIMEOUT_INVALID, isThrow);
return nullptr;
}
if (!GetNamedStringValue(env, argv[0], reason)) {
Common::HandleParamErr(env, ERR_REASON_NULL_OR_TYPE_ERR, isThrow);
return nullptr;
}
if (!GetNamedBoolValue(env, argv[0], "isPersist", isPersist, false)) {
Common::HandleParamErr(env, ERR_ISPERSIST_NULL_OR_TYPE_ERR, isThrow);
return nullptr;
}
if (!GetNamedBoolValue(env, argv[0], "isProcess", isProcess, false)) {
Common::HandleParamErr(env, ERR_ISPROCESS_NULL_OR_TYPE_ERR, isThrow);
return nullptr;
}
if (!GetNamedInt32Value(env, argv[0], "cpuLevel", cpuLevel, false)) {
Common::HandleParamErr(env, ERR_BGTASK_EFFICIENCY_RESOURCES_CPU_LEVEL_INVALID, isThrow);
return nullptr;
}
params = EfficiencyResourceInfo {resourceNumber, isApply, timeOut, reason, isPersist, isProcess};
params.SetCpuLevel(cpuLevel);
return Common::NapiGetNull(env);
}
bool CheckValidInfo(napi_env env, const EfficiencyResourceInfo ¶ms, bool isThrow)
{
if (params.GetResourceNumber() == 0) {
Common::HandleParamErr(env, ERR_RESOURCE_TYPES_INVALID, isThrow);
return false;
}
if (params.IsApply() && !params.IsPersist() && params.GetTimeOut() == 0) {
Common::HandleParamErr(env, ERR_TIMEOUT_INVALID, isThrow);
return false;
}
return true;
}
napi_value ApplyEfficiencyResources(napi_env env, napi_callback_info info)
{
HitraceScoped traceScoped(HITRACE_TAG_OHOS,
"BackgroundTaskManager::EfficiencyResource::Napi::ApplyEfficiencyResources");
EfficiencyResourceInfo params;
if (ParseParameters(env, info, params, true) == nullptr || !CheckValidInfo(env, params, true)) {
return Common::NapiGetNull(env);
}
ErrCode errCode = DelayedSingleton<BackgroundTaskManager>::GetInstance()->ApplyEfficiencyResources(params);
Common::HandleErrCode(env, errCode, true);
return Common::NapiGetNull(env);
}
napi_value ResetAllEfficiencyResources(napi_env env, napi_callback_info info)
{
HitraceScoped traceScoped(HITRACE_TAG_OHOS,
"BackgroundTaskManager::EfficiencyResource::Napi::ResetAllEfficiencyResources");
ErrCode errCode = DelayedSingleton<BackgroundTaskManager>::GetInstance()->ResetAllEfficiencyResources();
Common::HandleErrCode(env, errCode, true);
return Common::NapiGetNull(env);
}
void GetAllEfficiencyResourcesAsyncWork(napi_env env, void *data)
{
AsyncCallbackInfoGetAllEfficiencyResources *asyncCallbackInfo =
static_cast<AsyncCallbackInfoGetAllEfficiencyResources *>(data);
if (asyncCallbackInfo == nullptr || asyncCallbackInfo->errCode != ERR_OK) {
BGTASK_LOGE("asyncCallbackInfo is nullptr");
return;
}
asyncCallbackInfo->errCode = DelayedSingleton<BackgroundTaskManager>::GetInstance()->
GetAllEfficiencyResources(asyncCallbackInfo->efficiencyResourceInfoList);
}
void GetAllEfficiencyResourcesAsyncWork(napi_env env, napi_status status, void *data)
{
AsyncCallbackInfoGetAllEfficiencyResources *asyncCallbackInfo =
static_cast<AsyncCallbackInfoGetAllEfficiencyResources *>(data);
if (asyncCallbackInfo == nullptr) {
BGTASK_LOGE("asyncCallbackInfo is nullptr");
return;
}
napi_value result = nullptr;
if (asyncCallbackInfo->errCode == ERR_OK) {
NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &result));
if (asyncCallbackInfo->efficiencyResourceInfoList.size() > 0) {
uint32_t count = 0;
for (const auto &efficiencyResourceTaskInfo : asyncCallbackInfo->efficiencyResourceInfoList) {
napi_value napiWork = Common::GetNapiEfficiencyResourcesInfo(env, efficiencyResourceTaskInfo);
NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, count, napiWork));
count++;
}
}
NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result));
} else {
std::string errMsg = Common::FindErrMsg(env, asyncCallbackInfo->errCode);
int32_t errCodeInfo = Common::FindErrCode(env, asyncCallbackInfo->errCode);
result = Common::GetCallbackErrorValue(env, errCodeInfo, errMsg);
NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result));
}
}
napi_value GetAllEfficiencyResources(napi_env env, napi_callback_info info)
{
HitraceScoped traceScoped(HITRACE_TAG_OHOS,
"BackgroundTaskManager::EfficiencyResource::Napi::GetAllEfficiencyResources");
napi_ref callback = nullptr;
napi_value promise = nullptr;
AsyncCallbackInfoGetAllEfficiencyResources *asyncCallbackInfo =
new (std::nothrow)AsyncCallbackInfoGetAllEfficiencyResources(env);
if (!asyncCallbackInfo) {
BGTASK_LOGE("asyncCallbackInfo is nullptr");
return Common::JSParaError(env, callback);
}
std::unique_ptr<AsyncCallbackInfoGetAllEfficiencyResources> callbackPtr {asyncCallbackInfo};
Common::PaddingAsyncWorkData(env, callback, *asyncCallbackInfo, promise);
napi_value resourceName = nullptr;
NAPI_CALL(env, napi_create_string_latin1(env, "GetAllEfficiencyResources", NAPI_AUTO_LENGTH, &resourceName));
NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
[](napi_env env, void *data) {
GetAllEfficiencyResourcesAsyncWork(env, data);
},
[](napi_env env, napi_status status, void *data) {
GetAllEfficiencyResourcesAsyncWork(env, status, data);
},
static_cast<AsyncCallbackInfoGetAllEfficiencyResources *>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
if (asyncCallbackInfo->isCallback) {
callbackPtr.release();
return Common::NapiGetNull(env);
} else {
callbackPtr.release();
return promise;
}
}
}
}