• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "battery_stats.h"
17 
18 #include <cstdio>
19 #include <cstdlib>
20 #include <string>
21 #include <vector>
22 
23 #include "napi/native_api.h"
24 
25 #include "battery_stats_client.h"
26 #include "stats_hilog_wrapper.h"
27 
28 using namespace OHOS::PowerMgr;
29 
SetValueInt32(const napi_env & env,std::string fieldStr,const int intValue,napi_value & result)30 static void SetValueInt32(const napi_env& env, std::string fieldStr, const int intValue, napi_value& result)
31 {
32     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
33     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Set int32_t value: %{public}d", intValue);
34     napi_value value;
35     napi_create_int32(env, intValue, &value);
36     napi_set_named_property(env, result, fieldStr.c_str(), value);
37     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
38 }
39 
SetValueDouble(const napi_env & env,std::string fieldStr,const double doubleValue,napi_value & result)40 static void SetValueDouble(const napi_env& env, std::string fieldStr, const double doubleValue, napi_value& result)
41 {
42     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
43     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Set double value: %{public}lf", doubleValue);
44     napi_value value;
45     napi_create_double(env, doubleValue, &value);
46     napi_set_named_property(env, result, fieldStr.c_str(), value);
47     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
48 }
49 
StatsInfoToJsArray(const napi_env & env,const std::vector<BatteryStats> & vecJsStatsInfo,const int idx,napi_value & arrayResult)50 static void StatsInfoToJsArray(const napi_env& env, const std::vector<BatteryStats>& vecJsStatsInfo,
51     const int idx, napi_value& arrayResult)
52 {
53     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
54     napi_value result;
55     napi_create_object(env, &result);
56 
57     SetValueInt32(env, "uid", vecJsStatsInfo[idx].uid_, result);
58     SetValueInt32(env, "type", vecJsStatsInfo[idx].type_, result);
59     SetValueDouble(env, "power", vecJsStatsInfo[idx].power_, result);
60 
61     napi_status status = napi_set_element(env, arrayResult, idx, result);
62     if (status != napi_ok) {
63         STATS_HILOGE(STATS_MODULE_JS_NAPI, "BatteryStats js napi set element error: %{public}d", status);
64     }
65     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
66 }
67 
NativeCppStatsInfoToJsStatsInfo(const BatteryStatsInfoList & vecCppStatsInfos,std::vector<BatteryStats> & vecJsStatsInfo)68 static void NativeCppStatsInfoToJsStatsInfo(const BatteryStatsInfoList& vecCppStatsInfos,
69     std::vector<BatteryStats>& vecJsStatsInfo)
70 {
71     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
72     for (auto& e : vecCppStatsInfos) {
73         BatteryStats jsStatsInfo;
74 
75         jsStatsInfo.uid_ = e->GetUid();
76         jsStatsInfo.type_ = e->GetConsumptionType();
77         jsStatsInfo.power_ = e->GetPower();
78         vecJsStatsInfo.push_back(jsStatsInfo);
79     }
80     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
81 }
82 
GetBatteryStatsInfoList(std::vector<BatteryStats> & vecStatsInfo)83 static bool GetBatteryStatsInfoList(std::vector<BatteryStats>& vecStatsInfo)
84 {
85     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
86     BatteryStatsInfoList vecCppStatsInfos = BatteryStatsClient::GetInstance().GetBatteryStats();
87     if (vecCppStatsInfos.size() <= 0) {
88         STATS_HILOGE(STATS_MODULE_JS_NAPI, "Get Stats info failed");
89         return false;
90     }
91 
92     STATS_HILOGD(STATS_MODULE_JS_NAPI, "StatsInfoList size: %{public}d", (int)vecCppStatsInfos.size());
93     NativeCppStatsInfoToJsStatsInfo(vecCppStatsInfos, vecStatsInfo);
94     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
95     return true;
96 }
97 
BatteryStatsToNapiValue(napi_env env,std::vector<BatteryStats> & vecStatsInfo,napi_value & result)98 static void BatteryStatsToNapiValue(napi_env env, std::vector<BatteryStats>& vecStatsInfo, napi_value& result)
99 {
100     napi_status status = napi_create_array_with_length(env, vecStatsInfo.size(), &result);
101     if (status != napi_ok) {
102         STATS_HILOGE(STATS_MODULE_JS_NAPI, "BatteryStats napi_create_array_with_length error: %{public}d", status);
103         return;
104     }
105     for (size_t i = 0; i < vecStatsInfo.size(); ++i) {
106         StatsInfoToJsArray(env, vecStatsInfo, i, result);
107     }
108 }
109 
StatsInfoToPromise(const napi_env & env,AsyncCallbackInfo * asCallbackInfo,napi_value & promise)110 static napi_value StatsInfoToPromise(const napi_env& env, AsyncCallbackInfo *asCallbackInfo, napi_value& promise)
111 {
112     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
113     napi_value resourceName;
114     napi_create_string_latin1(env, "getBatteryStats", NAPI_AUTO_LENGTH, &resourceName);
115 
116     napi_deferred deferred;
117     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
118     asCallbackInfo->deferred = deferred;
119 
120     napi_create_async_work(
121         env,
122         nullptr,
123         resourceName,
124         [](napi_env env, void *data) {
125             AsyncCallbackInfo *asCallbackInfo = (AsyncCallbackInfo *)data;
126             GetBatteryStatsInfoList(asCallbackInfo->vecStatsInfo);
127         },
128         [](napi_env env, napi_status status, void *data) {
129             AsyncCallbackInfo *asCallbackInfo = (AsyncCallbackInfo *)data;
130             napi_value result = nullptr;
131             if (!asCallbackInfo->vecStatsInfo.empty()) {
132                 BatteryStatsToNapiValue(env, asCallbackInfo->vecStatsInfo, result);
133                 napi_resolve_deferred(env, asCallbackInfo->deferred, result);
134             } else {
135                 napi_reject_deferred(env, asCallbackInfo->deferred, result);
136             }
137             napi_delete_async_work(env, asCallbackInfo->asyncWork);
138             delete asCallbackInfo;
139         },
140         (void *)asCallbackInfo,
141         &asCallbackInfo->asyncWork);
142     napi_queue_async_work(env, asCallbackInfo->asyncWork);
143     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
144     return NULL;
145 }
146 
StatsInfoToCallBack(const napi_env & env,AsyncCallbackInfo * asCallbackInfo,const size_t argc,const napi_value * argv)147 static napi_value StatsInfoToCallBack(const napi_env& env, AsyncCallbackInfo *asCallbackInfo,
148     const size_t argc, const napi_value *argv)
149 {
150     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
151     napi_value resourceName;
152     napi_create_string_latin1(env, "getBatteryStats", NAPI_AUTO_LENGTH, &resourceName);
153 
154     for (size_t i = 0; i != argc; ++i) {
155         napi_valuetype valuetype;
156         NAPI_CALL(env, napi_typeof(env, argv[i], &valuetype));
157         NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected.");
158         napi_create_reference(env, argv[i], 1, &asCallbackInfo->callback[i]);
159     }
160 
161     napi_create_async_work(
162         env, nullptr, resourceName,
163         [](napi_env env, void* data) {
164             AsyncCallbackInfo *asCallbackInfo = (AsyncCallbackInfo *)data;
165             GetBatteryStatsInfoList(asCallbackInfo->vecStatsInfo);
166         },
167         [](napi_env env, napi_status status, void* data) {
168             AsyncCallbackInfo* asCallbackInfo = (AsyncCallbackInfo *)data;
169             napi_value undefine;
170             napi_get_undefined(env, &undefine);
171             napi_value callback;
172             napi_value result = nullptr;
173             if (!asCallbackInfo->vecStatsInfo.empty()) {
174                 BatteryStatsToNapiValue(env, asCallbackInfo->vecStatsInfo, result);
175                 napi_get_reference_value(env, asCallbackInfo->callback[0], &callback);
176                 napi_call_function(env, nullptr, callback, 1, &result, &undefine);
177             } else {
178                 if (asCallbackInfo->callback[1]) {
179                     napi_get_reference_value(env, asCallbackInfo->callback[1], &callback);
180                     napi_call_function(env, nullptr, callback, 1, &result, &undefine);
181                 } else {
182                     STATS_HILOGE(STATS_MODULE_JS_NAPI, "StatsInfoList callback func is null");
183                     napi_throw_error(env, "error", "StatsInfoList callback func is null");
184                 }
185             }
186 
187             if (asCallbackInfo->callback[0] != nullptr) {
188                 napi_delete_reference(env, asCallbackInfo->callback[0]);
189             }
190             if (asCallbackInfo->callback[1] != nullptr) {
191                 napi_delete_reference(env, asCallbackInfo->callback[1]);
192             }
193             napi_delete_async_work(env, asCallbackInfo->asyncWork);
194             delete asCallbackInfo;
195         },
196         (void *)asCallbackInfo,
197         &asCallbackInfo->asyncWork);
198     NAPI_CALL(env, napi_queue_async_work(env, asCallbackInfo->asyncWork));
199     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
200     return NULL;
201 }
202 
GetBatteryStats(napi_env env,napi_callback_info info)203 static napi_value GetBatteryStats(napi_env env, napi_callback_info info)
204 {
205     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
206     size_t argc = 2;
207     napi_value argv[argc];
208     napi_value thisVar = nullptr;
209     void *data = nullptr;
210     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
211 
212     AsyncCallbackInfo *asCallbackInfo =
213         new AsyncCallbackInfo {.asyncWork = nullptr, .deferred = nullptr};
214 
215     if (argc >= 1) {
216         StatsInfoToCallBack(env, asCallbackInfo, argc, argv);
217         STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit_callback");
218         return NULL;
219     } else {
220         napi_value promise;
221         StatsInfoToPromise(env, asCallbackInfo, promise);
222         STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit_promise");
223         return promise;
224     }
225 }
226 
GetAppStatsMah(napi_env env,napi_callback_info info)227 static napi_value GetAppStatsMah(napi_env env, napi_callback_info info)
228 {
229     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
230     size_t argc = 1;
231     napi_value argv[1];
232     napi_value thisVar;
233     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
234     NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
235 
236     napi_valuetype type1;
237     napi_typeof(env, argv[0], &type1);
238     NAPI_ASSERT(env, type1 == napi_number, "Wrong argument type. napi_number expected.");
239 
240     int32_t uid;
241     napi_get_value_int32(env, argv[0], &uid);
242 
243     double appStatsMah = BatteryStatsClient::GetInstance().GetAppStatsMah(uid);
244 
245     napi_value result;
246     napi_create_double(env, appStatsMah, &result);
247     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Got stats mah: %{public}lf for uid: %{public}d", appStatsMah, uid);
248     return result;
249 }
250 
GetAppStatsPercent(napi_env env,napi_callback_info info)251 static napi_value GetAppStatsPercent(napi_env env, napi_callback_info info)
252 {
253     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
254     size_t argc = 1;
255     napi_value argv[1];
256     napi_value thisVar;
257     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
258     NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
259 
260     napi_valuetype type1;
261     napi_typeof(env, argv[0], &type1);
262     NAPI_ASSERT(env, type1 == napi_number, "Wrong argument type. napi_number expected.");
263 
264     int32_t uid;
265     napi_get_value_int32(env, argv[0], &uid);
266 
267     double appStatsPercent = BatteryStatsClient::GetInstance().GetAppStatsPercent(uid);
268 
269     napi_value result;
270     napi_create_double(env, appStatsPercent, &result);
271     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Got stats percent: %{public}lf for uid: %{public}d", appStatsPercent, uid);
272     return result;
273 }
274 
GetPartStatsMah(napi_env env,napi_callback_info info)275 static napi_value GetPartStatsMah(napi_env env, napi_callback_info info)
276 {
277     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
278     size_t argc = 1;
279     napi_value argv[1];
280     napi_value thisVar;
281     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
282     NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
283 
284     napi_valuetype type1;
285     napi_typeof(env, argv[0], &type1);
286     NAPI_ASSERT(env, type1 == napi_number, "Wrong argument type. napi_number expected.");
287 
288     int32_t typeJs;
289     napi_get_value_int32(env, argv[0], &typeJs);
290 
291     BatteryStatsInfo::ConsumptionType type = BatteryStatsInfo::ConsumptionType(typeJs);
292     double partStatsMah = BatteryStatsClient::GetInstance().GetPartStatsMah(type);
293 
294     napi_value result;
295     napi_create_double(env, partStatsMah, &result);
296     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Got stats mah: %{public}lf for type: %{public}d", partStatsMah, type);
297     return result;
298 }
299 
GetPartStatsPercent(napi_env env,napi_callback_info info)300 static napi_value GetPartStatsPercent(napi_env env, napi_callback_info info)
301 {
302     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
303     size_t argc = 1;
304     napi_value argv[1];
305     napi_value thisVar;
306     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
307     NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
308 
309     napi_valuetype type1;
310     napi_typeof(env, argv[0], &type1);
311     NAPI_ASSERT(env, type1 == napi_number, "Wrong argument type. napi_number expected.");
312 
313     int32_t typeJs;
314     napi_get_value_int32(env, argv[0], &typeJs);
315 
316     BatteryStatsInfo::ConsumptionType type = BatteryStatsInfo::ConsumptionType(typeJs);
317     double partStatsPercent = BatteryStatsClient::GetInstance().GetPartStatsPercent(type);
318 
319     napi_value result;
320     napi_create_double(env, partStatsPercent, &result);
321     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Got stats percent: %{public}lf for type: %{public}d", partStatsPercent, type);
322     return result;
323 }
324 
EnumStatsTypeConstructor(napi_env env,napi_callback_info info)325 static napi_value EnumStatsTypeConstructor(napi_env env, napi_callback_info info)
326 {
327     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
328     napi_value thisArg = nullptr;
329     void *data = nullptr;
330     napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
331     napi_value global = nullptr;
332     napi_get_global(env, &global);
333     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
334     return thisArg;
335 }
336 
CreateEnumStatsType(napi_env env,napi_value exports)337 static napi_value CreateEnumStatsType(napi_env env, napi_value exports)
338 {
339     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
340     napi_value invalid = nullptr;
341     napi_value app = nullptr;
342     napi_value bluetooth = nullptr;
343     napi_value idle = nullptr;
344     napi_value phone = nullptr;
345     napi_value radio = nullptr;
346     napi_value screen = nullptr;
347     napi_value user = nullptr;
348     napi_value wifi = nullptr;
349 
350     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_INVALID, &invalid);
351     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_APP, &app);
352     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_BLUETOOTH, &bluetooth);
353     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_IDLE, &idle);
354     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_PHONE, &phone);
355     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_RADIO, &radio);
356     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_SCREEN, &screen);
357     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_USER, &user);
358     napi_create_int32(env, (int32_t)BatteryStatsInfo::ConsumptionType::CONSUMPTION_TYPE_WIFI, &wifi);
359 
360     napi_property_descriptor desc[] = {
361         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_INVALID", invalid),
362         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_APP", app),
363         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_BLUETOOTH", bluetooth),
364         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_IDLE", idle),
365         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_PHONE", phone),
366         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_RADIO", radio),
367         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_SCREEN", screen),
368         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_USER", user),
369         DECLARE_NAPI_STATIC_PROPERTY("CONSUMPTION_TYPE_WIFI", wifi),
370     };
371     napi_value result = nullptr;
372     napi_define_class(env, "ConsumptionType", NAPI_AUTO_LENGTH, EnumStatsTypeConstructor, nullptr,
373         sizeof(desc) / sizeof(*desc), desc, &result);
374 
375     napi_set_named_property(env, exports, "ConsumptionType", result);
376     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
377     return exports;
378 }
379 
380 EXTERN_C_START
381 /*
382  * function for module exports
383  */
BatteryStatsInit(napi_env env,napi_value exports)384 static napi_value BatteryStatsInit(napi_env env, napi_value exports)
385 {
386     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Enter");
387 
388     napi_property_descriptor desc[] = {
389         DECLARE_NAPI_FUNCTION("getBatteryStats", GetBatteryStats),
390         DECLARE_NAPI_FUNCTION("getAppPowerValue", GetAppStatsMah),
391         DECLARE_NAPI_FUNCTION("getAppPowerPercent", GetAppStatsPercent),
392         DECLARE_NAPI_FUNCTION("getHardwareUnitPowerValue", GetPartStatsMah),
393         DECLARE_NAPI_FUNCTION("getHardwareUnitPowerPercent", GetPartStatsPercent),
394     };
395     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
396 
397     CreateEnumStatsType(env, exports);
398     STATS_HILOGD(STATS_MODULE_JS_NAPI, "Exit");
399     return exports;
400 }
401 EXTERN_C_END
402 
403 /*
404  * Module definition
405  */
406 static napi_module batteryStatsModule = {
407     .nm_version = 1,
408     .nm_flags = 0,
409     .nm_filename = "batteryStats",
410     .nm_register_func = BatteryStatsInit,
411     .nm_modname = "batteryStatistics",
412     .nm_priv = ((void *)0),
413     .reserved = {0}
414 };
415 
416 /*
417  * Module registration
418  */
RegisterModule(void)419 extern "C" __attribute__((constructor)) void RegisterModule(void)
420 {
421     napi_module_register(&batteryStatsModule);
422 }
423