137a09cd7Sopenharmony_ci/* 237a09cd7Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 337a09cd7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 437a09cd7Sopenharmony_ci * you may not use this file except in compliance with the License. 537a09cd7Sopenharmony_ci * You may obtain a copy of the License at 637a09cd7Sopenharmony_ci * 737a09cd7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 837a09cd7Sopenharmony_ci * 937a09cd7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1037a09cd7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1137a09cd7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1237a09cd7Sopenharmony_ci * See the License for the specific language governing permissions and 1337a09cd7Sopenharmony_ci * limitations under the License. 1437a09cd7Sopenharmony_ci */ 1537a09cd7Sopenharmony_ci 1637a09cd7Sopenharmony_ci#include "thermal_manager_napi.h" 1737a09cd7Sopenharmony_ci 1837a09cd7Sopenharmony_ci#include <uv.h> 1937a09cd7Sopenharmony_ci 2037a09cd7Sopenharmony_ci#include "napi_utils.h" 2137a09cd7Sopenharmony_ci#include "napi_errors.h" 2237a09cd7Sopenharmony_ci#include "thermal_common.h" 2337a09cd7Sopenharmony_ci#include "thermal_level_info.h" 2437a09cd7Sopenharmony_ci 2537a09cd7Sopenharmony_ciusing namespace OHOS::PowerMgr; 2637a09cd7Sopenharmony_ciusing namespace OHOS; 2737a09cd7Sopenharmony_ci 2837a09cd7Sopenharmony_cinamespace { 2937a09cd7Sopenharmony_ciconst uint8_t ARG_0 = 0; 3037a09cd7Sopenharmony_ciconst uint8_t ARG_1 = 1; 3137a09cd7Sopenharmony_ciconstexpr uint32_t MAX_ARGC = 1; 3237a09cd7Sopenharmony_cithread_local auto& g_thermalMgrClient = ThermalMgrClient::GetInstance(); 3337a09cd7Sopenharmony_cithread_local sptr<ThermalLevelCallback> g_thermalLevelCallback = new (std::nothrow) ThermalLevelCallback(); 3437a09cd7Sopenharmony_ci} // namespace 3537a09cd7Sopenharmony_ci 3637a09cd7Sopenharmony_ciThermalLevelCallback::~ThermalLevelCallback() 3737a09cd7Sopenharmony_ci{ 3837a09cd7Sopenharmony_ci ReleaseCallback(); 3937a09cd7Sopenharmony_ci} 4037a09cd7Sopenharmony_ci 4137a09cd7Sopenharmony_civoid ThermalLevelCallback::UpdateCallback(napi_env env, napi_value jsCallback) 4237a09cd7Sopenharmony_ci{ 4337a09cd7Sopenharmony_ci std::lock_guard lock(mutex_); 4437a09cd7Sopenharmony_ci if (napi_ok != napi_create_reference(env, jsCallback, 1, &callbackRef_)) { 4537a09cd7Sopenharmony_ci THERMAL_HILOGW(COMP_FWK, "Failed to create a JS callback reference"); 4637a09cd7Sopenharmony_ci callbackRef_ = nullptr; 4737a09cd7Sopenharmony_ci } 4837a09cd7Sopenharmony_ci env_ = env; 4937a09cd7Sopenharmony_ci} 5037a09cd7Sopenharmony_ci 5137a09cd7Sopenharmony_civoid ThermalLevelCallback::ReleaseCallback() 5237a09cd7Sopenharmony_ci{ 5337a09cd7Sopenharmony_ci std::lock_guard lock(mutex_); 5437a09cd7Sopenharmony_ci if (callbackRef_ != nullptr) { 5537a09cd7Sopenharmony_ci napi_delete_reference(env_, callbackRef_); 5637a09cd7Sopenharmony_ci } 5737a09cd7Sopenharmony_ci callbackRef_ = nullptr; 5837a09cd7Sopenharmony_ci env_ = nullptr; 5937a09cd7Sopenharmony_ci} 6037a09cd7Sopenharmony_ci 6137a09cd7Sopenharmony_cibool ThermalLevelCallback::OnThermalLevelChanged(ThermalLevel level) 6237a09cd7Sopenharmony_ci{ 6337a09cd7Sopenharmony_ci std::lock_guard lock(mutex_); 6437a09cd7Sopenharmony_ci level_ = level; 6537a09cd7Sopenharmony_ci THERMAL_RETURN_IF_WITH_RET(env_ == nullptr, false); 6637a09cd7Sopenharmony_ci uv_loop_s* loop = nullptr; 6737a09cd7Sopenharmony_ci napi_get_uv_event_loop(env_, &loop); 6837a09cd7Sopenharmony_ci THERMAL_RETURN_IF_WITH_RET(loop == nullptr, false); 6937a09cd7Sopenharmony_ci uv_work_t* work = new (std::nothrow) uv_work_t; 7037a09cd7Sopenharmony_ci THERMAL_RETURN_IF_WITH_RET(work == nullptr, false); 7137a09cd7Sopenharmony_ci work->data = reinterpret_cast<void*>(this); 7237a09cd7Sopenharmony_ci 7337a09cd7Sopenharmony_ci int32_t ret = uv_queue_work_with_qos( 7437a09cd7Sopenharmony_ci loop, work, 7537a09cd7Sopenharmony_ci [](uv_work_t* work) { 7637a09cd7Sopenharmony_ci THERMAL_HILOGD(COMP_FWK, "uv_queue_work callback function is called"); 7737a09cd7Sopenharmony_ci }, 7837a09cd7Sopenharmony_ci [](uv_work_t* work, int status) { 7937a09cd7Sopenharmony_ci ThermalLevelCallback* callback = reinterpret_cast<ThermalLevelCallback*>(work->data); 8037a09cd7Sopenharmony_ci if (callback != nullptr) { 8137a09cd7Sopenharmony_ci callback->OnThermalLevel(); 8237a09cd7Sopenharmony_ci } 8337a09cd7Sopenharmony_ci delete work; 8437a09cd7Sopenharmony_ci work = nullptr; 8537a09cd7Sopenharmony_ci }, 8637a09cd7Sopenharmony_ci uv_qos_utility); 8737a09cd7Sopenharmony_ci if (ret != ERR_OK) { 8837a09cd7Sopenharmony_ci delete work; 8937a09cd7Sopenharmony_ci work = nullptr; 9037a09cd7Sopenharmony_ci THERMAL_HILOGW(COMP_FWK, "uv_queue_work is failed"); 9137a09cd7Sopenharmony_ci return false; 9237a09cd7Sopenharmony_ci } 9337a09cd7Sopenharmony_ci return true; 9437a09cd7Sopenharmony_ci} 9537a09cd7Sopenharmony_ci 9637a09cd7Sopenharmony_civoid ThermalLevelCallback::OnThermalLevel() 9737a09cd7Sopenharmony_ci{ 9837a09cd7Sopenharmony_ci THERMAL_HILOGD(COMP_FWK, "level is: %{public}d", static_cast<int32_t>(level_)); 9937a09cd7Sopenharmony_ci THERMAL_RETURN_IF_WITH_LOG(callbackRef_ == nullptr || env_ == nullptr, "js callback ref or env is nullptr"); 10037a09cd7Sopenharmony_ci 10137a09cd7Sopenharmony_ci napi_handle_scope scope = nullptr; 10237a09cd7Sopenharmony_ci napi_open_handle_scope(env_, &scope); 10337a09cd7Sopenharmony_ci if (scope == nullptr) { 10437a09cd7Sopenharmony_ci THERMAL_HILOGW(COMP_FWK, "scope is nullptr"); 10537a09cd7Sopenharmony_ci return; 10637a09cd7Sopenharmony_ci } 10737a09cd7Sopenharmony_ci 10837a09cd7Sopenharmony_ci napi_value levelValue = nullptr; 10937a09cd7Sopenharmony_ci if (napi_ok != napi_create_int32(env_, static_cast<int32_t>(level_), &levelValue)) { 11037a09cd7Sopenharmony_ci THERMAL_HILOGW(COMP_FWK, "napi_create_int32 callback failed"); 11137a09cd7Sopenharmony_ci napi_close_handle_scope(env_, scope); 11237a09cd7Sopenharmony_ci return; 11337a09cd7Sopenharmony_ci } 11437a09cd7Sopenharmony_ci 11537a09cd7Sopenharmony_ci napi_value callback = nullptr; 11637a09cd7Sopenharmony_ci napi_status status = napi_get_reference_value(env_, callbackRef_, &callback); 11737a09cd7Sopenharmony_ci if (status != napi_ok) { 11837a09cd7Sopenharmony_ci THERMAL_HILOGE(COMP_FWK, "napi_get_reference_value callback failed, status = %{public}d", status); 11937a09cd7Sopenharmony_ci napi_close_handle_scope(env_, scope); 12037a09cd7Sopenharmony_ci return; 12137a09cd7Sopenharmony_ci } 12237a09cd7Sopenharmony_ci 12337a09cd7Sopenharmony_ci napi_value callResult = nullptr; 12437a09cd7Sopenharmony_ci status = napi_call_function(env_, nullptr, callback, ARG_1, &levelValue, &callResult); 12537a09cd7Sopenharmony_ci if (status != napi_ok) { 12637a09cd7Sopenharmony_ci THERMAL_HILOGE(COMP_FWK, "napi_call_function callback failed, status = %{public}d", status); 12737a09cd7Sopenharmony_ci } 12837a09cd7Sopenharmony_ci napi_close_handle_scope(env_, scope); 12937a09cd7Sopenharmony_ci} 13037a09cd7Sopenharmony_ci 13137a09cd7Sopenharmony_cinapi_value ThermalManagerNapi::Init(napi_env env, napi_value exports) 13237a09cd7Sopenharmony_ci{ 13337a09cd7Sopenharmony_ci napi_property_descriptor desc[] = { 13437a09cd7Sopenharmony_ci // Old Interface 13537a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_FUNCTION("subscribeThermalLevel", SubscribeThermalLevel), 13637a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_FUNCTION("unsubscribeThermalLevel", UnSubscribeThermalLevel), 13737a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_FUNCTION("getThermalLevel", GetThermalLevel), 13837a09cd7Sopenharmony_ci // New Interface 13937a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_FUNCTION("registerThermalLevelCallback", SubscribeThermalLevel), 14037a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_FUNCTION("unregisterThermalLevelCallback", UnSubscribeThermalLevel), 14137a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_FUNCTION("getLevel", GetThermalLevel), 14237a09cd7Sopenharmony_ci }; 14337a09cd7Sopenharmony_ci NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); 14437a09cd7Sopenharmony_ci InitThermalLevel(env, exports); 14537a09cd7Sopenharmony_ci 14637a09cd7Sopenharmony_ci return exports; 14737a09cd7Sopenharmony_ci} 14837a09cd7Sopenharmony_ci 14937a09cd7Sopenharmony_cinapi_value ThermalManagerNapi::InitThermalLevel(napi_env env, napi_value exports) 15037a09cd7Sopenharmony_ci{ 15137a09cd7Sopenharmony_ci napi_value cool; 15237a09cd7Sopenharmony_ci napi_value normal; 15337a09cd7Sopenharmony_ci napi_value warm; 15437a09cd7Sopenharmony_ci napi_value hot; 15537a09cd7Sopenharmony_ci napi_value overheated; 15637a09cd7Sopenharmony_ci napi_value warning; 15737a09cd7Sopenharmony_ci napi_value emergency; 15837a09cd7Sopenharmony_ci napi_value escape; 15937a09cd7Sopenharmony_ci 16037a09cd7Sopenharmony_ci napi_create_uint32(env, static_cast<uint32_t>(ThermalLevel::COOL), &cool); 16137a09cd7Sopenharmony_ci napi_create_uint32(env, static_cast<uint32_t>(ThermalLevel::NORMAL), &normal); 16237a09cd7Sopenharmony_ci napi_create_uint32(env, static_cast<uint32_t>(ThermalLevel::WARM), &warm); 16337a09cd7Sopenharmony_ci napi_create_uint32(env, static_cast<uint32_t>(ThermalLevel::HOT), &hot); 16437a09cd7Sopenharmony_ci napi_create_uint32(env, static_cast<uint32_t>(ThermalLevel::OVERHEATED), &overheated); 16537a09cd7Sopenharmony_ci napi_create_uint32(env, static_cast<uint32_t>(ThermalLevel::WARNING), &warning); 16637a09cd7Sopenharmony_ci napi_create_uint32(env, static_cast<uint32_t>(ThermalLevel::EMERGENCY), &emergency); 16737a09cd7Sopenharmony_ci napi_create_uint32(env, static_cast<uint32_t>(ThermalLevel::ESCAPE), &escape); 16837a09cd7Sopenharmony_ci 16937a09cd7Sopenharmony_ci napi_property_descriptor desc[] = { 17037a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_PROPERTY("COOL", cool), 17137a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_PROPERTY("NORMAL", normal), 17237a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_PROPERTY("WARM", warm), 17337a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_PROPERTY("HOT", hot), 17437a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_PROPERTY("OVERHEATED", overheated), 17537a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_PROPERTY("WARNING", warning), 17637a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_PROPERTY("EMERGENCY", emergency), 17737a09cd7Sopenharmony_ci DECLARE_NAPI_STATIC_PROPERTY("ESCAPE", escape), 17837a09cd7Sopenharmony_ci }; 17937a09cd7Sopenharmony_ci 18037a09cd7Sopenharmony_ci napi_value result = nullptr; 18137a09cd7Sopenharmony_ci napi_define_class(env, "ThermalLevel", NAPI_AUTO_LENGTH, EnumThermalLevelConstructor, nullptr, 18237a09cd7Sopenharmony_ci sizeof(desc) / sizeof(*desc), desc, &result); 18337a09cd7Sopenharmony_ci napi_set_named_property(env, exports, "ThermalLevel", result); 18437a09cd7Sopenharmony_ci return exports; 18537a09cd7Sopenharmony_ci} 18637a09cd7Sopenharmony_ci 18737a09cd7Sopenharmony_cinapi_value ThermalManagerNapi::EnumThermalLevelConstructor(napi_env env, napi_callback_info info) 18837a09cd7Sopenharmony_ci{ 18937a09cd7Sopenharmony_ci size_t argc = 0; 19037a09cd7Sopenharmony_ci napi_value argv[ARG_1] = {0}; 19137a09cd7Sopenharmony_ci napi_value jsthis = nullptr; 19237a09cd7Sopenharmony_ci void* data = nullptr; 19337a09cd7Sopenharmony_ci 19437a09cd7Sopenharmony_ci napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsthis, &data); 19537a09cd7Sopenharmony_ci 19637a09cd7Sopenharmony_ci THERMAL_HILOGI(COMP_FWK, "EnumThermalLevelConstructor %{public}d", status); 19737a09cd7Sopenharmony_ci if (status != napi_ok) { 19837a09cd7Sopenharmony_ci return nullptr; 19937a09cd7Sopenharmony_ci } 20037a09cd7Sopenharmony_ci return jsthis; 20137a09cd7Sopenharmony_ci} 20237a09cd7Sopenharmony_ci 20337a09cd7Sopenharmony_cinapi_value ThermalManagerNapi::GetThermalLevel(napi_env env, napi_callback_info info) 20437a09cd7Sopenharmony_ci{ 20537a09cd7Sopenharmony_ci ThermalLevel level = g_thermalMgrClient.GetThermalLevel(); 20637a09cd7Sopenharmony_ci int32_t levelValue = static_cast<int32_t>(level); 20737a09cd7Sopenharmony_ci napi_value napiValue; 20837a09cd7Sopenharmony_ci NAPI_CALL(env, napi_create_int32(env, levelValue, &napiValue)); 20937a09cd7Sopenharmony_ci 21037a09cd7Sopenharmony_ci THERMAL_HILOGI(COMP_FWK, "level is %{public}d", levelValue); 21137a09cd7Sopenharmony_ci return napiValue; 21237a09cd7Sopenharmony_ci} 21337a09cd7Sopenharmony_ci 21437a09cd7Sopenharmony_cinapi_value ThermalManagerNapi::SubscribeThermalLevel(napi_env env, napi_callback_info info) 21537a09cd7Sopenharmony_ci{ 21637a09cd7Sopenharmony_ci size_t argc = MAX_ARGC; 21737a09cd7Sopenharmony_ci napi_value argv[argc]; 21837a09cd7Sopenharmony_ci NapiUtils::GetCallbackInfo(env, info, argc, argv); 21937a09cd7Sopenharmony_ci 22037a09cd7Sopenharmony_ci NapiErrors error; 22137a09cd7Sopenharmony_ci if (argc != MAX_ARGC || !NapiUtils::CheckValueType(env, argv[ARG_0], napi_function)) { 22237a09cd7Sopenharmony_ci return error.ThrowError(env, ThermalErrors::ERR_PARAM_INVALID); 22337a09cd7Sopenharmony_ci } 22437a09cd7Sopenharmony_ci 22537a09cd7Sopenharmony_ci napi_value result; 22637a09cd7Sopenharmony_ci napi_get_undefined(env, &result); 22737a09cd7Sopenharmony_ci 22837a09cd7Sopenharmony_ci THERMAL_RETURN_IF_WITH_RET(g_thermalLevelCallback == nullptr, result); 22937a09cd7Sopenharmony_ci g_thermalLevelCallback->ReleaseCallback(); 23037a09cd7Sopenharmony_ci g_thermalLevelCallback->UpdateCallback(env, argv[ARG_0]); 23137a09cd7Sopenharmony_ci g_thermalMgrClient.SubscribeThermalLevelCallback(g_thermalLevelCallback); 23237a09cd7Sopenharmony_ci 23337a09cd7Sopenharmony_ci return result; 23437a09cd7Sopenharmony_ci} 23537a09cd7Sopenharmony_ci 23637a09cd7Sopenharmony_cinapi_value ThermalManagerNapi::UnSubscribeThermalLevel(napi_env env, napi_callback_info info) 23737a09cd7Sopenharmony_ci{ 23837a09cd7Sopenharmony_ci size_t argc = MAX_ARGC; 23937a09cd7Sopenharmony_ci napi_value argv[argc]; 24037a09cd7Sopenharmony_ci NapiUtils::GetCallbackInfo(env, info, argc, argv); 24137a09cd7Sopenharmony_ci 24237a09cd7Sopenharmony_ci THERMAL_RETURN_IF_WITH_RET(g_thermalLevelCallback == nullptr, nullptr); 24337a09cd7Sopenharmony_ci g_thermalLevelCallback->ReleaseCallback(); 24437a09cd7Sopenharmony_ci g_thermalMgrClient.UnSubscribeThermalLevelCallback(g_thermalLevelCallback); 24537a09cd7Sopenharmony_ci 24637a09cd7Sopenharmony_ci THERMAL_RETURN_IF_WITH_RET(argc == ARG_0, nullptr); 24737a09cd7Sopenharmony_ci NapiErrors error; 24837a09cd7Sopenharmony_ci if (argc > MAX_ARGC || !NapiUtils::CheckValueType(env, argv[ARG_0], napi_function)) { 24937a09cd7Sopenharmony_ci return error.ThrowError(env, ThermalErrors::ERR_PARAM_INVALID); 25037a09cd7Sopenharmony_ci } 25137a09cd7Sopenharmony_ci 25237a09cd7Sopenharmony_ci napi_value handler = nullptr; 25337a09cd7Sopenharmony_ci napi_ref handlerRef = nullptr; 25437a09cd7Sopenharmony_ci napi_create_reference(env, argv[ARG_0], 1, &handlerRef); 25537a09cd7Sopenharmony_ci napi_get_reference_value(env, handlerRef, &handler); 25637a09cd7Sopenharmony_ci napi_delete_reference(env, handlerRef); 25737a09cd7Sopenharmony_ci 25837a09cd7Sopenharmony_ci napi_value result = nullptr; 25937a09cd7Sopenharmony_ci if (handler == nullptr) { 26037a09cd7Sopenharmony_ci THERMAL_HILOGW(COMP_FWK, "Handler should not be nullptr"); 26137a09cd7Sopenharmony_ci return result; 26237a09cd7Sopenharmony_ci } 26337a09cd7Sopenharmony_ci 26437a09cd7Sopenharmony_ci napi_get_undefined(env, &result); 26537a09cd7Sopenharmony_ci napi_status status = napi_call_function(env, nullptr, handler, ARG_0, nullptr, &result); 26637a09cd7Sopenharmony_ci if (status != napi_ok) { 26737a09cd7Sopenharmony_ci THERMAL_HILOGW(COMP_FWK, "status=%{public}d", status); 26837a09cd7Sopenharmony_ci return result; 26937a09cd7Sopenharmony_ci } 27037a09cd7Sopenharmony_ci return result; 27137a09cd7Sopenharmony_ci} 27237a09cd7Sopenharmony_ci 27337a09cd7Sopenharmony_ciEXTERN_C_START 27437a09cd7Sopenharmony_ci/* 27537a09cd7Sopenharmony_ci * function for module exports 27637a09cd7Sopenharmony_ci */ 27737a09cd7Sopenharmony_cistatic napi_value ThermalInit(napi_env env, napi_value exports) 27837a09cd7Sopenharmony_ci{ 27937a09cd7Sopenharmony_ci THERMAL_HILOGD(COMP_FWK, "Enter"); 28037a09cd7Sopenharmony_ci 28137a09cd7Sopenharmony_ci napi_value ret = ThermalManagerNapi::Init(env, exports); 28237a09cd7Sopenharmony_ci 28337a09cd7Sopenharmony_ci THERMAL_HILOGD(COMP_FWK, "Exit"); 28437a09cd7Sopenharmony_ci 28537a09cd7Sopenharmony_ci return ret; 28637a09cd7Sopenharmony_ci} 28737a09cd7Sopenharmony_ciEXTERN_C_END 28837a09cd7Sopenharmony_ci 28937a09cd7Sopenharmony_ci/* 29037a09cd7Sopenharmony_ci * Module definition 29137a09cd7Sopenharmony_ci */ 29237a09cd7Sopenharmony_cistatic napi_module g_module = {.nm_version = 1, 29337a09cd7Sopenharmony_ci .nm_flags = 0, 29437a09cd7Sopenharmony_ci .nm_filename = "thermal", 29537a09cd7Sopenharmony_ci .nm_register_func = ThermalInit, 29637a09cd7Sopenharmony_ci .nm_modname = "thermal", 29737a09cd7Sopenharmony_ci .nm_priv = ((void*)0), 29837a09cd7Sopenharmony_ci .reserved = {0}}; 29937a09cd7Sopenharmony_ci 30037a09cd7Sopenharmony_ci/* 30137a09cd7Sopenharmony_ci * Module registration 30237a09cd7Sopenharmony_ci */ 30337a09cd7Sopenharmony_ciextern "C" __attribute__((constructor)) void RegisterModule() 30437a09cd7Sopenharmony_ci{ 30537a09cd7Sopenharmony_ci napi_module_register(&g_module); 30637a09cd7Sopenharmony_ci} 307