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