1f16e0440Sopenharmony_ci/*
2f16e0440Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3f16e0440Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4f16e0440Sopenharmony_ci * you may not use this file except in compliance with the License.
5f16e0440Sopenharmony_ci * You may obtain a copy of the License at
6f16e0440Sopenharmony_ci *
7f16e0440Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8f16e0440Sopenharmony_ci *
9f16e0440Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10f16e0440Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11f16e0440Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f16e0440Sopenharmony_ci * See the License for the specific language governing permissions and
13f16e0440Sopenharmony_ci * limitations under the License.
14f16e0440Sopenharmony_ci */
15f16e0440Sopenharmony_ci
16f16e0440Sopenharmony_ci#include "system_battery.h"
17f16e0440Sopenharmony_ci
18f16e0440Sopenharmony_ci#include <string>
19f16e0440Sopenharmony_ci#include <cstddef>
20f16e0440Sopenharmony_ci#include <memory>
21f16e0440Sopenharmony_ci#include "new"
22f16e0440Sopenharmony_ci#include "napi/native_common.h"
23f16e0440Sopenharmony_ci
24f16e0440Sopenharmony_ci#include "battery_log.h"
25f16e0440Sopenharmony_ci#include "battery_srv_client.h"
26f16e0440Sopenharmony_ci#include "power_common.h"
27f16e0440Sopenharmony_ci
28f16e0440Sopenharmony_ciusing namespace OHOS::PowerMgr;
29f16e0440Sopenharmony_ci
30f16e0440Sopenharmony_cinamespace {
31f16e0440Sopenharmony_ciconst uint32_t MAX_ARGC = 1;
32f16e0440Sopenharmony_ciconst uint32_t ARGC_ONE = 0;
33f16e0440Sopenharmony_ciconst double LEVEL_RANGES = 0.01;
34f16e0440Sopenharmony_ci
35f16e0440Sopenharmony_ciconst std::string RESPONSE_CHARGING = "charging";
36f16e0440Sopenharmony_ciconst std::string RESPONSE_LEVEL = "level";
37f16e0440Sopenharmony_ciconst std::string FUNC_SUCEESS_NAME = "success";
38f16e0440Sopenharmony_ciconst std::string FUNC_FAIL_NAME = "fail";
39f16e0440Sopenharmony_ciconst std::string FUNC_COMPLETE_NAME = "complete";
40f16e0440Sopenharmony_ci
41f16e0440Sopenharmony_ciconst uint32_t COMMON_ERROR_COED = 200;
42f16e0440Sopenharmony_ciconst std::string GET_BATTERY_ERROR_MSG = "Battery level is not available";
43f16e0440Sopenharmony_ci}
44f16e0440Sopenharmony_ci
45f16e0440Sopenharmony_civoid SystemBattery::GetBatteryStats(napi_env env)
46f16e0440Sopenharmony_ci{
47f16e0440Sopenharmony_ci    if (!batteryInfo_.GetBatteryInfo()) {
48f16e0440Sopenharmony_ci        error_.SetErrorMsg(COMMON_ERROR_COED, GET_BATTERY_ERROR_MSG);
49f16e0440Sopenharmony_ci    }
50f16e0440Sopenharmony_ci    if (!error_.IsError()) {
51f16e0440Sopenharmony_ci        BATTERY_HILOGD(FEATURE_BATT_INFO, "Call the js success method");
52f16e0440Sopenharmony_ci        SuccessCallback(env);
53f16e0440Sopenharmony_ci    } else {
54f16e0440Sopenharmony_ci        BATTERY_HILOGD(FEATURE_BATT_INFO, "Call the js fail method");
55f16e0440Sopenharmony_ci        FailCallback(env);
56f16e0440Sopenharmony_ci    }
57f16e0440Sopenharmony_ci    BATTERY_HILOGD(FEATURE_BATT_INFO, "Call the js complete method");
58f16e0440Sopenharmony_ci    CompleteCallback(env);
59f16e0440Sopenharmony_ci}
60f16e0440Sopenharmony_ci
61f16e0440Sopenharmony_cinapi_value SystemBattery::CreateResponse(napi_env env)
62f16e0440Sopenharmony_ci{
63f16e0440Sopenharmony_ci    napi_value level = nullptr;
64f16e0440Sopenharmony_ci    napi_value charging = nullptr;
65f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_create_double(env, batteryInfo_.GetLevel(), &level));
66f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_create_uint32(env, batteryInfo_.IsCharging(), &charging));
67f16e0440Sopenharmony_ci
68f16e0440Sopenharmony_ci    napi_value response = nullptr;
69f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_create_object(env, &response));
70f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_set_named_property(env, response, RESPONSE_CHARGING.c_str(), charging));
71f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_set_named_property(env, response, RESPONSE_LEVEL.c_str(), level));
72f16e0440Sopenharmony_ci    return response;
73f16e0440Sopenharmony_ci}
74f16e0440Sopenharmony_ci
75f16e0440Sopenharmony_cibool SystemBattery::CheckValueType(napi_env env, napi_value value, napi_valuetype checkType)
76f16e0440Sopenharmony_ci{
77f16e0440Sopenharmony_ci    napi_valuetype valueType = napi_undefined;
78f16e0440Sopenharmony_ci    napi_typeof(env, value, &valueType);
79f16e0440Sopenharmony_ci    if (valueType != checkType) {
80f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "Check input parameter error");
81f16e0440Sopenharmony_ci        return false;
82f16e0440Sopenharmony_ci    }
83f16e0440Sopenharmony_ci    return true;
84f16e0440Sopenharmony_ci}
85f16e0440Sopenharmony_ci
86f16e0440Sopenharmony_cinapi_value SystemBattery::GetOptionsFunc(napi_env env, napi_value options, const std::string& name)
87f16e0440Sopenharmony_ci{
88f16e0440Sopenharmony_ci    napi_value property = nullptr;
89f16e0440Sopenharmony_ci    napi_status status = napi_get_named_property(env, options, name.c_str(), &property);
90f16e0440Sopenharmony_ci    if (status != napi_ok) {
91f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "Failed to obtain %{public}s", name.c_str());
92f16e0440Sopenharmony_ci        return nullptr;
93f16e0440Sopenharmony_ci    }
94f16e0440Sopenharmony_ci    if (!CheckValueType(env, property, napi_function)) {
95f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "The %{public}s argument is not a function", name.c_str());
96f16e0440Sopenharmony_ci        return nullptr;
97f16e0440Sopenharmony_ci    }
98f16e0440Sopenharmony_ci    return property;
99f16e0440Sopenharmony_ci}
100f16e0440Sopenharmony_ci
101f16e0440Sopenharmony_cibool SystemBattery::CreateCallbackRef(napi_env env, napi_value options)
102f16e0440Sopenharmony_ci{
103f16e0440Sopenharmony_ci    RETURN_IF_WITH_RET(!CheckValueType(env, options, napi_object), false);
104f16e0440Sopenharmony_ci
105f16e0440Sopenharmony_ci    napi_value succCallBack = GetOptionsFunc(env, options, FUNC_SUCEESS_NAME);
106f16e0440Sopenharmony_ci    if (succCallBack != nullptr) {
107f16e0440Sopenharmony_ci        napi_create_reference(env, succCallBack, 1, &successRef_);
108f16e0440Sopenharmony_ci    }
109f16e0440Sopenharmony_ci
110f16e0440Sopenharmony_ci    napi_value failCallBack = GetOptionsFunc(env, options, FUNC_FAIL_NAME);
111f16e0440Sopenharmony_ci    if (failCallBack != nullptr) {
112f16e0440Sopenharmony_ci        napi_create_reference(env, failCallBack, 1, &failRef_);
113f16e0440Sopenharmony_ci    }
114f16e0440Sopenharmony_ci
115f16e0440Sopenharmony_ci    napi_value completeCallBack = GetOptionsFunc(env, options, FUNC_COMPLETE_NAME);
116f16e0440Sopenharmony_ci    if (completeCallBack != nullptr) {
117f16e0440Sopenharmony_ci        napi_create_reference(env, completeCallBack, 1, &completeRef_);
118f16e0440Sopenharmony_ci    }
119f16e0440Sopenharmony_ci    return true;
120f16e0440Sopenharmony_ci}
121f16e0440Sopenharmony_ci
122f16e0440Sopenharmony_civoid SystemBattery::SuccessCallback(napi_env env)
123f16e0440Sopenharmony_ci{
124f16e0440Sopenharmony_ci    RETURN_IF(successRef_ == nullptr);
125f16e0440Sopenharmony_ci    napi_value success = nullptr;
126f16e0440Sopenharmony_ci    napi_get_reference_value(env, successRef_, &success);
127f16e0440Sopenharmony_ci    napi_value argv = nullptr;
128f16e0440Sopenharmony_ci    argv = CreateResponse(env);
129f16e0440Sopenharmony_ci    if (argv == nullptr) {
130f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "Failed to create BatteryResponse");
131f16e0440Sopenharmony_ci        napi_delete_reference(env, successRef_);
132f16e0440Sopenharmony_ci        return;
133f16e0440Sopenharmony_ci    }
134f16e0440Sopenharmony_ci
135f16e0440Sopenharmony_ci    napi_value callResult = 0;
136f16e0440Sopenharmony_ci    const size_t argc = 1;
137f16e0440Sopenharmony_ci    napi_status status = napi_call_function(env, nullptr, success, argc, &argv, &callResult);
138f16e0440Sopenharmony_ci    napi_delete_reference(env, successRef_);
139f16e0440Sopenharmony_ci    if (status != napi_ok) {
140f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "Failed to execute the callback function SUCCESS");
141f16e0440Sopenharmony_ci        return;
142f16e0440Sopenharmony_ci    }
143f16e0440Sopenharmony_ci    BATTERY_HILOGI(FEATURE_BATT_INFO, "Callbacks to incoming parameters, level: %{public}f, isCharging: %{public}d",
144f16e0440Sopenharmony_ci        batteryInfo_.GetLevel(), batteryInfo_.IsCharging());
145f16e0440Sopenharmony_ci}
146f16e0440Sopenharmony_ci
147f16e0440Sopenharmony_civoid SystemBattery::FailCallback(napi_env env)
148f16e0440Sopenharmony_ci{
149f16e0440Sopenharmony_ci    RETURN_IF(failRef_ == nullptr);
150f16e0440Sopenharmony_ci    napi_value fail = nullptr;
151f16e0440Sopenharmony_ci    napi_get_reference_value(env, failRef_, &fail);
152f16e0440Sopenharmony_ci
153f16e0440Sopenharmony_ci    napi_value data = nullptr;
154f16e0440Sopenharmony_ci    napi_value code = nullptr;
155f16e0440Sopenharmony_ci    std::string msg = error_.GetMsg();
156f16e0440Sopenharmony_ci    napi_status strStatus = napi_create_string_utf8(env, msg.c_str(), msg.size(), &data);
157f16e0440Sopenharmony_ci    napi_status intStatus = napi_create_int32(env, error_.GetCode(), &code);
158f16e0440Sopenharmony_ci    if (strStatus != napi_ok || intStatus != napi_ok) {
159f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "Napi failed to create a parameter, code: %{public}d, msg: %{public}s",
160f16e0440Sopenharmony_ci            error_.GetCode(), msg.c_str());
161f16e0440Sopenharmony_ci        napi_delete_reference(env, failRef_);
162f16e0440Sopenharmony_ci        return;
163f16e0440Sopenharmony_ci    }
164f16e0440Sopenharmony_ci
165f16e0440Sopenharmony_ci    napi_value argv[] = { data, code };
166f16e0440Sopenharmony_ci    napi_value callResult = 0;
167f16e0440Sopenharmony_ci    const size_t argc = 2;
168f16e0440Sopenharmony_ci    napi_status status = napi_call_function(env, nullptr, fail, argc, argv, &callResult);
169f16e0440Sopenharmony_ci    if (status != napi_ok) {
170f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "Call fail function is failed");
171f16e0440Sopenharmony_ci    }
172f16e0440Sopenharmony_ci    napi_delete_reference(env, failRef_);
173f16e0440Sopenharmony_ci}
174f16e0440Sopenharmony_ci
175f16e0440Sopenharmony_civoid SystemBattery::CompleteCallback(napi_env env)
176f16e0440Sopenharmony_ci{
177f16e0440Sopenharmony_ci    RETURN_IF(completeRef_ == nullptr);
178f16e0440Sopenharmony_ci    napi_value complete = nullptr;
179f16e0440Sopenharmony_ci    napi_get_reference_value(env, completeRef_, &complete);
180f16e0440Sopenharmony_ci    napi_value callResult = 0;
181f16e0440Sopenharmony_ci    const size_t argc = 0;
182f16e0440Sopenharmony_ci    napi_status status = napi_call_function(env, nullptr, complete, argc, nullptr, &callResult);
183f16e0440Sopenharmony_ci    if (status != napi_ok) {
184f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "Call complete function is failed");
185f16e0440Sopenharmony_ci    }
186f16e0440Sopenharmony_ci    napi_delete_reference(env, completeRef_);
187f16e0440Sopenharmony_ci}
188f16e0440Sopenharmony_ci
189f16e0440Sopenharmony_civoid SystemBattery::Error::SetErrorMsg(int32_t code, const std::string& msg)
190f16e0440Sopenharmony_ci{
191f16e0440Sopenharmony_ci    code_ = code;
192f16e0440Sopenharmony_ci    msg_ = msg;
193f16e0440Sopenharmony_ci    BATTERY_HILOGW(FEATURE_BATT_INFO, "Error message, code: %{public}d, msg: %{public}s",
194f16e0440Sopenharmony_ci        code_, msg_.c_str());
195f16e0440Sopenharmony_ci}
196f16e0440Sopenharmony_ci
197f16e0440Sopenharmony_cibool SystemBattery::BatteryInfo::GetBatteryInfo()
198f16e0440Sopenharmony_ci{
199f16e0440Sopenharmony_ci    BatterySrvClient& g_battClient = BatterySrvClient::GetInstance();
200f16e0440Sopenharmony_ci    capacity_ = g_battClient.GetCapacity();
201f16e0440Sopenharmony_ci    chargingState_ = g_battClient.GetChargingStatus();
202f16e0440Sopenharmony_ci    BATTERY_HILOGI(FEATURE_BATT_INFO, "Get battery info, capacity: %{public}d, charging: %{public}d",
203f16e0440Sopenharmony_ci        capacity_, static_cast<int32_t>(chargingState_));
204f16e0440Sopenharmony_ci    return (capacity_ != INVALID_BATT_INT_VALUE) && (chargingState_ != BatteryChargeState::CHARGE_STATE_BUTT);
205f16e0440Sopenharmony_ci}
206f16e0440Sopenharmony_ci
207f16e0440Sopenharmony_cidouble SystemBattery::BatteryInfo::GetLevel() const
208f16e0440Sopenharmony_ci{
209f16e0440Sopenharmony_ci    // Current battery level, which ranges from 0.00 to 1.00.
210f16e0440Sopenharmony_ci    return (capacity_ * LEVEL_RANGES);
211f16e0440Sopenharmony_ci}
212f16e0440Sopenharmony_ci
213f16e0440Sopenharmony_ciuint32_t SystemBattery::BatteryInfo::IsCharging() const
214f16e0440Sopenharmony_ci{
215f16e0440Sopenharmony_ci    return static_cast<uint32_t>(chargingState_ == BatteryChargeState::CHARGE_STATE_ENABLE ||
216f16e0440Sopenharmony_ci        chargingState_ == BatteryChargeState::CHARGE_STATE_FULL);
217f16e0440Sopenharmony_ci}
218f16e0440Sopenharmony_ci
219f16e0440Sopenharmony_cistatic napi_value GetStatus(napi_env env, napi_callback_info info)
220f16e0440Sopenharmony_ci{
221f16e0440Sopenharmony_ci    BATTERY_HILOGD(FEATURE_BATT_INFO, "Call the GetBatteryStats method");
222f16e0440Sopenharmony_ci    size_t argc = MAX_ARGC;
223f16e0440Sopenharmony_ci    napi_value argv[argc];
224f16e0440Sopenharmony_ci    napi_value thisVar = nullptr;
225f16e0440Sopenharmony_ci    void *data = nullptr;
226f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
227f16e0440Sopenharmony_ci
228f16e0440Sopenharmony_ci    if (argc != MAX_ARGC) {
229f16e0440Sopenharmony_ci        BATTERY_HILOGW(FEATURE_BATT_INFO, "Lack of parameter, argc: %{public}zu", argc);
230f16e0440Sopenharmony_ci        return nullptr;
231f16e0440Sopenharmony_ci    }
232f16e0440Sopenharmony_ci
233f16e0440Sopenharmony_ci    std::unique_ptr<SystemBattery> asyncInfo = std::make_unique<SystemBattery>();
234f16e0440Sopenharmony_ci    RETURN_IF_WITH_RET(!asyncInfo->CreateCallbackRef(env, argv[ARGC_ONE]), nullptr);
235f16e0440Sopenharmony_ci
236f16e0440Sopenharmony_ci    napi_value resource = nullptr;
237f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_create_string_utf8(env, "GetStatus", NAPI_AUTO_LENGTH, &resource));
238f16e0440Sopenharmony_ci    napi_create_async_work(
239f16e0440Sopenharmony_ci        env,
240f16e0440Sopenharmony_ci        nullptr,
241f16e0440Sopenharmony_ci        resource,
242f16e0440Sopenharmony_ci        [](napi_env env, void *data) {
243f16e0440Sopenharmony_ci	    BATTERY_HILOGD(FEATURE_BATT_INFO, "async_work callback function is called");
244f16e0440Sopenharmony_ci	},
245f16e0440Sopenharmony_ci        [](napi_env env, napi_status status, void *data) {
246f16e0440Sopenharmony_ci            SystemBattery *asyncInfo = reinterpret_cast<SystemBattery*>(data);
247f16e0440Sopenharmony_ci            if (asyncInfo != nullptr) {
248f16e0440Sopenharmony_ci                asyncInfo->GetBatteryStats(env);
249f16e0440Sopenharmony_ci                napi_delete_async_work(env, asyncInfo->asyncWork);
250f16e0440Sopenharmony_ci                delete asyncInfo;
251f16e0440Sopenharmony_ci            }
252f16e0440Sopenharmony_ci        },
253f16e0440Sopenharmony_ci        reinterpret_cast<void*>(asyncInfo.get()),
254f16e0440Sopenharmony_ci        &asyncInfo->asyncWork);
255f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncInfo->asyncWork, napi_qos_utility));
256f16e0440Sopenharmony_ci    asyncInfo.release();
257f16e0440Sopenharmony_ci    return nullptr;
258f16e0440Sopenharmony_ci}
259f16e0440Sopenharmony_ci
260f16e0440Sopenharmony_ciEXTERN_C_START
261f16e0440Sopenharmony_ci/*
262f16e0440Sopenharmony_ci * function for module exports
263f16e0440Sopenharmony_ci */
264f16e0440Sopenharmony_cistatic napi_value SystemBatteryInit(napi_env env, napi_value exports)
265f16e0440Sopenharmony_ci{
266f16e0440Sopenharmony_ci    BATTERY_HILOGI(COMP_FWK, "SystemBattery init");
267f16e0440Sopenharmony_ci    napi_property_descriptor desc[] = {
268f16e0440Sopenharmony_ci        DECLARE_NAPI_FUNCTION("getStatus", GetStatus)
269f16e0440Sopenharmony_ci    };
270f16e0440Sopenharmony_ci    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
271f16e0440Sopenharmony_ci    BATTERY_HILOGI(COMP_FWK, "SystemBattery init end");
272f16e0440Sopenharmony_ci    return exports;
273f16e0440Sopenharmony_ci}
274f16e0440Sopenharmony_ciEXTERN_C_END
275f16e0440Sopenharmony_ci
276f16e0440Sopenharmony_ci/*
277f16e0440Sopenharmony_ci * Module definition
278f16e0440Sopenharmony_ci */
279f16e0440Sopenharmony_cistatic napi_module g_module = {
280f16e0440Sopenharmony_ci    .nm_version = 1,
281f16e0440Sopenharmony_ci    .nm_flags = 0,
282f16e0440Sopenharmony_ci    .nm_filename = "battery",
283f16e0440Sopenharmony_ci    .nm_register_func = SystemBatteryInit,
284f16e0440Sopenharmony_ci    .nm_modname = "battery",
285f16e0440Sopenharmony_ci    .nm_priv = ((void*)0),
286f16e0440Sopenharmony_ci    .reserved = {0}
287f16e0440Sopenharmony_ci};
288f16e0440Sopenharmony_ci
289f16e0440Sopenharmony_ci/*
290f16e0440Sopenharmony_ci * Module registration
291f16e0440Sopenharmony_ci */
292f16e0440Sopenharmony_ciextern "C" __attribute__((constructor)) void RegisterModule(void)
293f16e0440Sopenharmony_ci{
294f16e0440Sopenharmony_ci    napi_module_register(&g_module);
295f16e0440Sopenharmony_ci}
296