• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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