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 <string>
17 #include "securec.h"
18 
19 #include "bundle_active_log.h"
20 #include "bundle_state_common.h"
21 #include "bundle_state_data.h"
22 #include "app_group_observer_napi.h"
23 #include "bundle_state_inner_errors.h"
24 
25 namespace OHOS {
26 namespace DeviceUsageStats {
27 const uint32_t IS_IDLE_STATE_MIN_PARAMS = 1;
28 const uint32_t IS_IDLE_STATE_PARAMS = 2;
29 const uint32_t PRIORITY_GROUP_MIN_PARAMS = 0;
30 const uint32_t PRIORITY_GROUP_MIDDLE_PARAMS = 1;
31 const uint32_t PRIORITY_GROUP_PARAMS = 2;
32 const uint32_t STATES_MIN_PARAMS = 2;
33 const uint32_t STATES_PARAMS = 3;
34 const uint32_t APP_USAGE_MIN_PARAMS_BY_INTERVAL = 3;
35 const uint32_t APP_USAGE_PARAMS_BY_INTERVAL = 4;
36 const uint32_t APP_USAGE_MIN_PARAMS = 2;
37 const uint32_t APP_USAGE_PARAMS = 3;
38 const uint32_t SECOND_ARG = 2;
39 const uint32_t THIRD_ARG = 3;
40 
ParseIsIdleStateParameters(const napi_env & env,const napi_callback_info & info,IsIdleStateParamsInfo & params)41 napi_value ParseIsIdleStateParameters(const napi_env &env, const napi_callback_info &info,
42     IsIdleStateParamsInfo &params)
43 {
44     size_t argc = IS_IDLE_STATE_PARAMS;
45     napi_value argv[IS_IDLE_STATE_PARAMS] = {nullptr};
46     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
47     NAPI_ASSERT(env, argc == IS_IDLE_STATE_MIN_PARAMS || argc == IS_IDLE_STATE_PARAMS,
48         "Invalid number of parameters");
49 
50     // argv[0] : bundleName
51     std::string result = "";
52     params.bundleName = BundleStateCommon::GetTypeStringValue(env, argv[0], result);
53     if (params.bundleName.empty()) {
54         BUNDLE_ACTIVE_LOGE("ParseIsIdleStateParameters failed, bundleName is empty.");
55         params.errorCode = ERR_USAGE_STATS_BUNDLENAME_EMPTY;
56     }
57     napi_valuetype valuetype;
58     NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
59     if ((valuetype != napi_string) && (params.errorCode == ERR_OK)) {
60         BUNDLE_ACTIVE_LOGE("Wrong argument type, string expected.");
61         params.errorCode = ERR_USAGE_STATS_BUNDLENAME_TYPE;
62     }
63 
64     // argv[1]: callback
65     if (argc == IS_IDLE_STATE_PARAMS) {
66         napi_valuetype inputValueType = napi_undefined;
67         NAPI_CALL(env, napi_typeof(env, argv[1], &inputValueType));
68         NAPI_ASSERT(env, inputValueType == napi_function,
69             "ParseIsIdleStateParameters invalid parameter type, function expected.");
70         napi_create_reference(env, argv[1], 1, &params.callback);
71     }
72     return BundleStateCommon::NapiGetNull(env);
73 }
74 
IsBundleIdleAsync(napi_env env,void * data)75 void IsBundleIdleAsync(napi_env env, void *data)
76 {
77     AsyncCallbackInfoIsIdleState *asyncCallbackInfo = (AsyncCallbackInfoIsIdleState *)data;
78     if (asyncCallbackInfo != nullptr) {
79         asyncCallbackInfo->errorCode = BundleActiveClient::GetInstance().IsBundleIdle(asyncCallbackInfo->state,
80             asyncCallbackInfo->bundleName);
81     } else {
82         BUNDLE_ACTIVE_LOGE("IsIdleState, asyncCallbackInfo == nullptr");
83     }
84 }
85 
IsBundleIdleAsyncCB(napi_env env,napi_status status,void * data)86 void IsBundleIdleAsyncCB(napi_env env, napi_status status, void *data)
87 {
88     AsyncCallbackInfoIsIdleState *asyncCallbackInfo = (AsyncCallbackInfoIsIdleState *)data;
89     if (asyncCallbackInfo != nullptr) {
90         napi_value result = nullptr;
91         napi_get_boolean(env, asyncCallbackInfo->state, &result);
92         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
93     }
94 }
95 
IsIdleState(napi_env env,napi_callback_info info)96 napi_value IsIdleState(napi_env env, napi_callback_info info)
97 {
98     IsIdleStateParamsInfo params;
99     ParseIsIdleStateParameters(env, info, params);
100     if (params.errorCode != ERR_OK) {
101         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
102     }
103     napi_value promise = nullptr;
104     AsyncCallbackInfoIsIdleState *asyncCallbackInfo =
105         new (std::nothrow) AsyncCallbackInfoIsIdleState(env);
106     if (!asyncCallbackInfo) {
107         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_NULLPTR;
108         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
109     }
110     if (memset_s(asyncCallbackInfo, sizeof(*asyncCallbackInfo), 0, sizeof(*asyncCallbackInfo)) != EOK) {
111         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_INIT_FAILED;
112         delete asyncCallbackInfo;
113         asyncCallbackInfo = nullptr;
114         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
115     }
116     std::unique_ptr<AsyncCallbackInfoIsIdleState> callbackPtr {asyncCallbackInfo};
117     callbackPtr->bundleName = params.bundleName;
118     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
119     napi_value resourceName = nullptr;
120     NAPI_CALL(env, napi_create_string_latin1(env, "IsIdleState", NAPI_AUTO_LENGTH, &resourceName));
121     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, IsBundleIdleAsync, IsBundleIdleAsyncCB,
122         static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
123     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
124     if (callbackPtr->isCallback) {
125         callbackPtr.release();
126         return BundleStateCommon::NapiGetNull(env);
127     } else {
128         callbackPtr.release();
129         return promise;
130     }
131 }
132 
ParsePriorityGroupParameters(const napi_env & env,const napi_callback_info & info,QueryAppGroupParamsInfo & params,AsyncQueryAppGroupCallbackInfo * & asyncCallbackInfo)133 napi_value ParsePriorityGroupParameters(const napi_env &env, const napi_callback_info &info,
134     QueryAppGroupParamsInfo &params, AsyncQueryAppGroupCallbackInfo* &asyncCallbackInfo)
135 {
136     size_t argc = PRIORITY_GROUP_PARAMS;
137     napi_value argv[PRIORITY_GROUP_PARAMS] = {nullptr};
138     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
139     NAPI_ASSERT(env, argc == PRIORITY_GROUP_MIN_PARAMS || argc == PRIORITY_GROUP_MIDDLE_PARAMS ||
140         argc == PRIORITY_GROUP_PARAMS, "Invalid number of parameters");
141     std::string result = "";
142     params.bundleName = "";
143     if (argc == PRIORITY_GROUP_MIDDLE_PARAMS) {
144         napi_valuetype valuetype = napi_undefined;
145         NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
146         if (valuetype == napi_function) {
147             napi_create_reference(env, argv[0], 1, &params.callback);
148         } else {
149             params.bundleName = BundleStateCommon::GetTypeStringValue(env, argv[0], result);
150             if (params.bundleName.empty()) {
151                 BUNDLE_ACTIVE_LOGE("ParsePriorityGroupParameters failed, bundleName is empty.");
152                 params.errorCode = ERR_USAGE_STATS_BUNDLENAME_EMPTY;
153             }
154         }
155     } else if (argc == PRIORITY_GROUP_PARAMS) {
156         // argv[0] : bundleName
157         params.bundleName = BundleStateCommon::GetTypeStringValue(env, argv[0], result);
158         if (params.bundleName.empty()) {
159             BUNDLE_ACTIVE_LOGE("ParsePriorityGroupParameters failed, bundleName is empty.");
160             params.errorCode = ERR_USAGE_STATS_BUNDLENAME_EMPTY;
161         }
162 
163         // argv[1]: callback
164         napi_valuetype valuetype = napi_undefined;
165         NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
166         NAPI_ASSERT(env, valuetype == napi_function, "ParsePriorityGroupParameters invalid parameter type. "
167             "Function expected.");
168         napi_create_reference(env, argv[1], 1, &params.callback);
169     }
170     BundleStateCommon::AsyncInit(env, params, asyncCallbackInfo);
171     return BundleStateCommon::NapiGetNull(env);
172 }
173 
QueryAppGroupAsync(napi_env env,void * data)174 void QueryAppGroupAsync(napi_env env, void *data)
175 {
176     AsyncQueryAppGroupCallbackInfo *asyncCallbackInfo = (AsyncQueryAppGroupCallbackInfo *)data;
177     if (asyncCallbackInfo) {
178         asyncCallbackInfo->errorCode = BundleActiveClient::GetInstance().QueryAppGroup(
179             asyncCallbackInfo->priorityGroup, asyncCallbackInfo->bundleName);
180     } else {
181         BUNDLE_ACTIVE_LOGE("QueryAppUsagePriorityGroup, asyncCallbackInfo == nullptr");
182     }
183 }
184 
QueryAppGroupAsyncCB(napi_env env,napi_status status,void * data)185 void QueryAppGroupAsyncCB(napi_env env, napi_status status, void *data)
186 {
187     AsyncQueryAppGroupCallbackInfo *asyncCallbackInfo = (AsyncQueryAppGroupCallbackInfo *)data;
188     if (asyncCallbackInfo) {
189         if (asyncCallbackInfo->priorityGroup == -1) {
190             asyncCallbackInfo->errorCode = ERR_SERVICE_FAILED;
191         }
192         napi_value result = nullptr;
193         napi_create_int32(env, asyncCallbackInfo->priorityGroup, &result);
194         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
195     }
196 }
197 
QueryAppUsagePriorityGroup(napi_env env,napi_callback_info info)198 napi_value QueryAppUsagePriorityGroup(napi_env env, napi_callback_info info)
199 {
200     QueryAppGroupParamsInfo params;
201     AsyncQueryAppGroupCallbackInfo *asyncCallbackInfo = nullptr;
202     ParsePriorityGroupParameters(env, info, params, asyncCallbackInfo);
203     if (params.errorCode != ERR_OK && !asyncCallbackInfo) {
204         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
205     }
206     std::unique_ptr<AsyncQueryAppGroupCallbackInfo> callbackPtr {asyncCallbackInfo};
207     callbackPtr->bundleName = params.bundleName;
208     BUNDLE_ACTIVE_LOGD("QueryAppUsagePriorityGroup callbackPtr->bundleName: %{public}s",
209         callbackPtr->bundleName.c_str());
210     napi_value promise = nullptr;
211     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
212     napi_value resourceName = nullptr;
213     NAPI_CALL(env, napi_create_string_latin1(env, "QueryAppUsagePriorityGroup", NAPI_AUTO_LENGTH, &resourceName));
214     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, QueryAppGroupAsync, QueryAppGroupAsyncCB,
215         static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
216     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
217     if (callbackPtr->isCallback) {
218         callbackPtr.release();
219         return BundleStateCommon::NapiGetNull(env);
220     } else {
221         callbackPtr.release();
222         return promise;
223     }
224 }
225 
ParseStatesParameters(const napi_env & env,const napi_callback_info & info,StatesParamsInfo & params)226 napi_value ParseStatesParameters(const napi_env &env, const napi_callback_info &info, StatesParamsInfo &params)
227 {
228     size_t argc = STATES_PARAMS;
229     napi_value argv[STATES_PARAMS] = {nullptr};
230     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
231     NAPI_ASSERT(env, argc == STATES_MIN_PARAMS || argc == STATES_PARAMS,
232         "Invalid number of parameters");
233 
234     // argv[0] : beginTime
235     if (BundleStateCommon::GetInt64NumberValue(env, argv[0], params.beginTime) == nullptr) {
236         BUNDLE_ACTIVE_LOGE("ParseStatesParameters failed, beginTime type is invalid.");
237         params.errorCode = ERR_USAGE_STATS_BEGIN_TIME_INVALID;
238     }
239     if ((params.errorCode == ERR_OK)
240         && (params.beginTime < TIME_NUMBER_MIN)) {
241         BUNDLE_ACTIVE_LOGE("ParseStatesParameters failed, beginTime value is invalid.");
242         params.errorCode = ERR_USAGE_STATS_BEGIN_TIME_INVALID;
243     }
244 
245     // argv[1] : endTime
246     if ((params.errorCode == ERR_OK)
247         && (BundleStateCommon::GetInt64NumberValue(env, argv[1], params.endTime) == nullptr)) {
248         BUNDLE_ACTIVE_LOGE("ParseStatesParameters failed, endTime type is invalid.");
249         params.errorCode = ERR_USAGE_STATS_END_TIME_INVALID;
250     }
251     if ((params.errorCode == ERR_OK)
252         && (params.endTime < TIME_NUMBER_MIN)) {
253         BUNDLE_ACTIVE_LOGE("ParseStatesParameters failed, endTime value is invalid.");
254         params.errorCode = ERR_USAGE_STATS_END_TIME_INVALID;
255     }
256     if ((params.errorCode == ERR_OK) && (params.endTime <= params.beginTime)) {
257         BUNDLE_ACTIVE_LOGE("ParseStatesParameters endTime(%{public}lld) <= beginTime(%{public}lld)",
258             (long long)params.endTime, (long long)params.beginTime);
259         params.errorCode = ERR_USAGE_STATS_TIME_INTERVAL;
260     }
261 
262     // argv[SECOND_ARG]: callback
263     if (argc == STATES_PARAMS) {
264         napi_valuetype valuetype = napi_undefined;
265         NAPI_CALL(env, napi_typeof(env, argv[SECOND_ARG], &valuetype));
266         NAPI_ASSERT(env, valuetype == napi_function, "ParseStatesParameters invalid parameter type. "
267             "Function expected.");
268         napi_create_reference(env, argv[SECOND_ARG], 1, &params.callback);
269     }
270     return BundleStateCommon::NapiGetNull(env);
271 }
272 
QueryCurrentBundleEventsAsync(napi_env env,void * data)273 void QueryCurrentBundleEventsAsync(napi_env env, void *data)
274 {
275     AsyncCallbackInfoStates *asyncCallbackInfo = (AsyncCallbackInfoStates *)data;
276     if (asyncCallbackInfo != nullptr) {
277         asyncCallbackInfo->errorCode =
278             BundleActiveClient::GetInstance().QueryCurrentBundleEvents(asyncCallbackInfo->BundleActiveState,
279                 asyncCallbackInfo->beginTime, asyncCallbackInfo->endTime);
280     } else {
281         BUNDLE_ACTIVE_LOGE("QueryCurrentBundleActiveStates, asyncCallbackInfo == nullptr");
282     }
283 }
284 
QueryCurrentBundleEventsAsyncCB(napi_env env,napi_status status,void * data)285 void QueryCurrentBundleEventsAsyncCB(napi_env env, napi_status status, void *data)
286 {
287     AsyncCallbackInfoStates *asyncCallbackInfo = (AsyncCallbackInfoStates *)data;
288     if (asyncCallbackInfo != nullptr) {
289         napi_value result = nullptr;
290         napi_create_array(env, &result);
291         BundleStateCommon::GetBundleActiveEventForResult(
292             env, asyncCallbackInfo->BundleActiveState, result, false);
293         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
294     }
295 }
296 
QueryCurrentBundleActiveStates(napi_env env,napi_callback_info info)297 napi_value QueryCurrentBundleActiveStates(napi_env env, napi_callback_info info)
298 {
299     StatesParamsInfo params;
300     ParseStatesParameters(env, info, params);
301     if (params.errorCode != ERR_OK) {
302         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
303     }
304     napi_value promise = nullptr;
305     AsyncCallbackInfoStates *asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfoStates(env);
306     if (!asyncCallbackInfo) {
307         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_NULLPTR;
308         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
309     }
310     if (memset_s(asyncCallbackInfo, sizeof(*asyncCallbackInfo), 0, sizeof(*asyncCallbackInfo)) != EOK) {
311         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_INIT_FAILED;
312         delete asyncCallbackInfo;
313         asyncCallbackInfo = nullptr;
314         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
315     }
316     std::unique_ptr<AsyncCallbackInfoStates> callbackPtr {asyncCallbackInfo};
317     callbackPtr->beginTime = params.beginTime;
318     BUNDLE_ACTIVE_LOGD("QueryCurrentBundleActiveStates callbackPtr->beginTime: %{public}lld",
319         (long long)callbackPtr->beginTime);
320     callbackPtr->endTime = params.endTime;
321     BUNDLE_ACTIVE_LOGD("QueryCurrentBundleActiveStates callbackPtr->endTime: %{public}lld",
322         (long long)callbackPtr->endTime);
323     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
324 
325     napi_value resourceName = nullptr;
326     NAPI_CALL(env, napi_create_string_latin1(env, "QueryCurrentBundleActiveStates", NAPI_AUTO_LENGTH, &resourceName));
327     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, QueryCurrentBundleEventsAsync,
328         QueryCurrentBundleEventsAsyncCB, static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
329     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
330     if (callbackPtr->isCallback) {
331         callbackPtr.release();
332         return BundleStateCommon::NapiGetNull(env);
333     } else {
334         callbackPtr.release();
335         return promise;
336     }
337 }
338 
QueryBundleEventsAsync(napi_env env,void * data)339 void QueryBundleEventsAsync(napi_env env, void *data)
340 {
341     AsyncCallbackInfoStates *asyncCallbackInfo = (AsyncCallbackInfoStates *)data;
342     if (asyncCallbackInfo != nullptr) {
343         asyncCallbackInfo->errorCode =
344             BundleActiveClient::GetInstance().QueryBundleEvents(asyncCallbackInfo->BundleActiveState,
345                 asyncCallbackInfo->beginTime, asyncCallbackInfo->endTime, asyncCallbackInfo->errorCode);
346     } else {
347         BUNDLE_ACTIVE_LOGE("QueryBundleActiveStates, asyncCallbackInfo == nullptr");
348     }
349 }
350 
QueryBundleEventsAsyncCB(napi_env env,napi_status status,void * data)351 void QueryBundleEventsAsyncCB(napi_env env, napi_status status, void *data)
352 {
353     AsyncCallbackInfoStates *asyncCallbackInfo = (AsyncCallbackInfoStates *)data;
354     if (asyncCallbackInfo != nullptr) {
355         napi_value result = nullptr;
356         napi_create_array(env, &result);
357         BundleStateCommon::GetBundleActiveEventForResult(
358             env, asyncCallbackInfo->BundleActiveState, result, false);
359         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
360     }
361 }
362 
QueryBundleActiveStates(napi_env env,napi_callback_info info)363 napi_value QueryBundleActiveStates(napi_env env, napi_callback_info info)
364 {
365     StatesParamsInfo params;
366     ParseStatesParameters(env, info, params);
367     if (params.errorCode != ERR_OK) {
368         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
369     }
370     napi_value promise = nullptr;
371     AsyncCallbackInfoStates *asyncCallbackInfo =
372         new (std::nothrow) AsyncCallbackInfoStates(env);
373     if (!asyncCallbackInfo) {
374         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_NULLPTR;
375         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
376     }
377     if (memset_s(asyncCallbackInfo, sizeof(*asyncCallbackInfo), 0, sizeof(*asyncCallbackInfo)) != EOK) {
378         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_INIT_FAILED;
379         delete asyncCallbackInfo;
380         asyncCallbackInfo = nullptr;
381         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
382     }
383     std::unique_ptr<AsyncCallbackInfoStates> callbackPtr {asyncCallbackInfo};
384     callbackPtr->beginTime = params.beginTime;
385     BUNDLE_ACTIVE_LOGD("QueryBundleActiveStates callbackPtr->beginTime: %{public}lld",
386         (long long)callbackPtr->beginTime);
387     callbackPtr->endTime = params.endTime;
388     BUNDLE_ACTIVE_LOGD("QueryBundleActiveStates callbackPtr->endTime: %{public}lld",
389         (long long)callbackPtr->endTime);
390     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
391 
392     napi_value resourceName = nullptr;
393     NAPI_CALL(env, napi_create_string_latin1(env, "QueryBundleActiveStates", NAPI_AUTO_LENGTH, &resourceName));
394     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, QueryBundleEventsAsync,
395         QueryBundleEventsAsyncCB, static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
396     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
397     if (callbackPtr->isCallback) {
398         callbackPtr.release();
399         return BundleStateCommon::NapiGetNull(env);
400     } else {
401         callbackPtr.release();
402         return promise;
403     }
404 }
405 
ParseAppUsageParametersByInterval(const napi_env & env,const napi_callback_info & info,AppUsageParamsByIntervalInfo & params)406 napi_value ParseAppUsageParametersByInterval(const napi_env &env, const napi_callback_info &info,
407     AppUsageParamsByIntervalInfo &params)
408 {
409     size_t argc = APP_USAGE_PARAMS_BY_INTERVAL;
410     napi_value argv[APP_USAGE_PARAMS_BY_INTERVAL] = {nullptr};
411     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
412     NAPI_ASSERT(env, argc == APP_USAGE_MIN_PARAMS_BY_INTERVAL || argc == APP_USAGE_PARAMS_BY_INTERVAL,
413         "Invalid number of parameters");
414     // argv[0] : intervalType
415     if (BundleStateCommon::GetInt32NumberValue(env, argv[0], params.intervalType) == nullptr) {
416         BUNDLE_ACTIVE_LOGE("ParseAppUsageParametersByInterval failed, intervalType is invalid.");
417         params.errorCode = ERR_USAGE_STATS_INTERVAL_TYPE;
418     }
419     if ((params.errorCode == ERR_OK) && ((params.intervalType < INTERVAL_NUMBER_MIN)
420         || (params.intervalType > INTERVAL_NUMBER_MAX))) {
421         BUNDLE_ACTIVE_LOGE("ParseAppUsageParametersByInterval failed, intervalType number is invalid.");
422         params.errorCode = ERR_USAGE_STATS_INTERVAL_NUMBER;
423     }
424     // argv[1] : beginTime
425     if ((params.errorCode == ERR_OK)
426         && (BundleStateCommon::GetInt64NumberValue(env, argv[1], params.beginTime) == nullptr)) {
427         BUNDLE_ACTIVE_LOGE("ParseAppUsageParametersByInterval failed, beginTime type is invalid.");
428         params.errorCode = ERR_USAGE_STATS_BEGIN_TIME_INVALID;
429     }
430     if ((params.errorCode == ERR_OK)
431         && (params.beginTime < TIME_NUMBER_MIN)) {
432         BUNDLE_ACTIVE_LOGE("ParseAppUsageParametersByInterval failed, beginTime value is invalid.");
433         params.errorCode = ERR_USAGE_STATS_BEGIN_TIME_INVALID;
434     }
435     // argv[SECOND_ARG] : endTime
436     if ((params.errorCode == ERR_OK)
437         && (BundleStateCommon::GetInt64NumberValue(env, argv[SECOND_ARG], params.endTime) == nullptr)) {
438         BUNDLE_ACTIVE_LOGE("ParseAppUsageParametersByInterval failed, endTime type is invalid.");
439         params.errorCode = ERR_USAGE_STATS_END_TIME_INVALID;
440     }
441     if ((params.errorCode == ERR_OK)
442         && (params.endTime < TIME_NUMBER_MIN)) {
443         BUNDLE_ACTIVE_LOGE("ParseAppUsageParametersByInterval failed, endTime value is invalid.");
444         params.errorCode = ERR_USAGE_STATS_END_TIME_INVALID;
445     }
446     if ((params.errorCode == ERR_OK) && (params.endTime <= params.beginTime)) {
447         BUNDLE_ACTIVE_LOGE("ParseAppUsageParametersByInterval endTime(%{public}lld) <= beginTime(%{public}lld)",
448             (long long)params.endTime, (long long)params.beginTime);
449         params.errorCode = ERR_USAGE_STATS_TIME_INTERVAL;
450     }
451     // argv[THIRD_ARG]: callback
452     if (argc == APP_USAGE_PARAMS_BY_INTERVAL) {
453         napi_valuetype valuetype = napi_undefined;
454         NAPI_CALL(env, napi_typeof(env, argv[THIRD_ARG], &valuetype));
455         NAPI_ASSERT(env, valuetype == napi_function, "ParseAppUsageParametersByInterval invalid parameter type. "
456             "Function expected.");
457         napi_create_reference(env, argv[THIRD_ARG], 1, &params.callback);
458     }
459     return BundleStateCommon::NapiGetNull(env);
460 }
461 
QueryBundleStatsInfoByIntervalAsync(napi_env env,void * data)462 void QueryBundleStatsInfoByIntervalAsync(napi_env env, void *data)
463 {
464     AsyncCallbackInfoAppUsageByInterval *asyncCallbackInfo = (AsyncCallbackInfoAppUsageByInterval *)data;
465     if (asyncCallbackInfo != nullptr) {
466         asyncCallbackInfo->errorCode =
467             BundleActiveClient::GetInstance().QueryBundleStatsInfoByInterval(asyncCallbackInfo->packageStats,
468                 asyncCallbackInfo->intervalType, asyncCallbackInfo->beginTime, asyncCallbackInfo->endTime);
469     } else {
470         BUNDLE_ACTIVE_LOGE("QueryBundleStateInfoByInterval, asyncCallbackInfo == nullptr");
471     }
472 }
473 
QueryBundleStatsInfoByIntervalAsyncCB(napi_env env,napi_status status,void * data)474 void QueryBundleStatsInfoByIntervalAsyncCB(napi_env env, napi_status status, void *data)
475 {
476     AsyncCallbackInfoAppUsageByInterval *asyncCallbackInfo = (AsyncCallbackInfoAppUsageByInterval *)data;
477     if (asyncCallbackInfo != nullptr) {
478         napi_value result = nullptr;
479         napi_create_array(env, &result);
480         BundleStateCommon::GetBundleStateInfoByIntervalForResult(env, asyncCallbackInfo->packageStats, result);
481         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
482     }
483 }
484 
QueryBundleStateInfoByInterval(napi_env env,napi_callback_info info)485 napi_value QueryBundleStateInfoByInterval(napi_env env, napi_callback_info info)
486 {
487     AppUsageParamsByIntervalInfo params;
488     ParseAppUsageParametersByInterval(env, info, params);
489     if (params.errorCode != ERR_OK) {
490         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
491     }
492     napi_value promise = nullptr;
493     AsyncCallbackInfoAppUsageByInterval *asyncCallbackInfo =
494         new (std::nothrow) AsyncCallbackInfoAppUsageByInterval(env);
495     if (!asyncCallbackInfo) {
496         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_NULLPTR;
497         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
498     }
499     if (memset_s(asyncCallbackInfo, sizeof(*asyncCallbackInfo), 0, sizeof(*asyncCallbackInfo)) != EOK) {
500         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_INIT_FAILED;
501         delete asyncCallbackInfo;
502         asyncCallbackInfo = nullptr;
503         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
504     }
505     std::unique_ptr<AsyncCallbackInfoAppUsageByInterval> callbackPtr {asyncCallbackInfo};
506     callbackPtr->intervalType = params.intervalType;
507     BUNDLE_ACTIVE_LOGD("QueryBundleStateInfoByInterval callbackPtr->intervalType: %{public}d",
508         callbackPtr->intervalType);
509     callbackPtr->beginTime = params.beginTime;
510     BUNDLE_ACTIVE_LOGD("QueryBundleStateInfoByInterval callbackPtr->beginTime: %{public}lld",
511         (long long)callbackPtr->beginTime);
512     callbackPtr->endTime = params.endTime;
513     BUNDLE_ACTIVE_LOGD("QueryBundleStateInfoByInterval callbackPtr->endTime: %{public}lld",
514         (long long)callbackPtr->endTime);
515     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
516     napi_value resourceName = nullptr;
517     NAPI_CALL(env, napi_create_string_latin1(env, "QueryBundleStateInfoByInterval", NAPI_AUTO_LENGTH, &resourceName));
518     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, QueryBundleStatsInfoByIntervalAsync,
519         QueryBundleStatsInfoByIntervalAsyncCB, static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
520     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
521     if (callbackPtr->isCallback) {
522         callbackPtr.release();
523         return BundleStateCommon::NapiGetNull(env);
524     } else {
525         callbackPtr.release();
526         return promise;
527     }
528 }
529 
ParseAppUsageParameters(const napi_env & env,const napi_callback_info & info,QueryBundleStatsParamsInfo & params)530 napi_value ParseAppUsageParameters(const napi_env &env, const napi_callback_info &info,
531     QueryBundleStatsParamsInfo &params)
532 {
533     size_t argc = APP_USAGE_PARAMS;
534     napi_value argv[APP_USAGE_PARAMS] = {nullptr};
535     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
536     NAPI_ASSERT(env, argc == APP_USAGE_MIN_PARAMS || argc == APP_USAGE_PARAMS,
537         "Invalid number of parameters");
538 
539     // argv[0] : beginTime
540     if (BundleStateCommon::GetInt64NumberValue(env, argv[0], params.beginTime) == nullptr) {
541         BUNDLE_ACTIVE_LOGE("ParseAppUsageParameters failed, beginTime type is invalid.");
542         params.errorCode = ERR_USAGE_STATS_BEGIN_TIME_INVALID;
543     }
544     if ((params.errorCode == ERR_OK) && (params.beginTime < TIME_NUMBER_MIN)) {
545         BUNDLE_ACTIVE_LOGE("ParseAppUsageParameters failed failed, beginTime value is invalid.");
546         params.errorCode = ERR_USAGE_STATS_BEGIN_TIME_INVALID;
547     }
548 
549     // argv[1] : endTime
550     if ((params.errorCode == ERR_OK)
551         && (BundleStateCommon::GetInt64NumberValue(env, argv[1], params.endTime) == nullptr)) {
552         BUNDLE_ACTIVE_LOGE("ParseAppUsageParameters failed, endTime type is invalid.");
553         params.errorCode = ERR_USAGE_STATS_END_TIME_INVALID;
554     }
555     if ((params.errorCode == ERR_OK) && (params.endTime < TIME_NUMBER_MIN)) {
556         BUNDLE_ACTIVE_LOGE("ParseAppUsageParameters failed failed, endTime value is invalid.");
557         params.errorCode = ERR_USAGE_STATS_END_TIME_INVALID;
558     }
559     if ((params.errorCode == ERR_OK) && (params.endTime <= params.beginTime)) {
560         BUNDLE_ACTIVE_LOGE("ParseAppUsageParameters endTime(%{public}lld) <= beginTime(%{public}lld)",
561             (long long)params.endTime, (long long)params.beginTime);
562         params.errorCode = ERR_USAGE_STATS_TIME_INTERVAL;
563     }
564 
565     // argv[SECOND_ARG]: callback
566     if (argc == APP_USAGE_PARAMS) {
567         napi_valuetype valuetype = napi_undefined;
568         NAPI_CALL(env, napi_typeof(env, argv[SECOND_ARG], &valuetype));
569         NAPI_ASSERT(env, valuetype == napi_function, "ParseAppUsageParameters invalid parameter type. "
570             "Function expected.");
571         napi_create_reference(env, argv[SECOND_ARG], 1, &params.callback);
572     }
573     return BundleStateCommon::NapiGetNull(env);
574 }
575 
QueryBundleStatsInfosAsync(napi_env env,void * data)576 void QueryBundleStatsInfosAsync(napi_env env, void *data)
577 {
578     AsyncCallbackInfoAppUsage *asyncCallbackInfo = (AsyncCallbackInfoAppUsage *)data;
579     if (asyncCallbackInfo != nullptr) {
580         asyncCallbackInfo->packageStats = BundleStateCommon::QueryBundleStatsInfos(asyncCallbackInfo->beginTime,
581             asyncCallbackInfo->endTime, asyncCallbackInfo->errorCode);
582     } else {
583         BUNDLE_ACTIVE_LOGE("QueryBundleStateInfos asyncCallbackInfo == nullptr");
584     }
585 }
586 
QueryBundleStatsInfosAsyncCB(napi_env env,napi_status status,void * data)587 void QueryBundleStatsInfosAsyncCB(napi_env env, napi_status status, void *data)
588 {
589     AsyncCallbackInfoAppUsage *asyncCallbackInfo = (AsyncCallbackInfoAppUsage *)data;
590     if (asyncCallbackInfo != nullptr) {
591         napi_value result = nullptr;
592         napi_create_object(env, &result);
593         BundleStateCommon::GetBundleStateInfoForResult(env, asyncCallbackInfo->packageStats, result);
594         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
595     }
596 }
597 
QueryBundleStateInfos(napi_env env,napi_callback_info info)598 napi_value QueryBundleStateInfos(napi_env env, napi_callback_info info)
599 {
600     QueryBundleStatsParamsInfo params;
601     ParseAppUsageParameters(env, info, params);
602     if (params.errorCode != ERR_OK) {
603         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
604     }
605     napi_value promise = nullptr;
606     AsyncCallbackInfoAppUsage *asyncCallbackInfo =
607         new (std::nothrow) AsyncCallbackInfoAppUsage(env);
608     if (!asyncCallbackInfo) {
609         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_NULLPTR;
610         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
611     }
612     if (memset_s(asyncCallbackInfo, sizeof(*asyncCallbackInfo), 0, sizeof(*asyncCallbackInfo)) != EOK) {
613         params.errorCode = ERR_USAGE_STATS_ASYNC_CALLBACK_INIT_FAILED;
614         delete asyncCallbackInfo;
615         asyncCallbackInfo = nullptr;
616         return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
617     }
618     std::unique_ptr<AsyncCallbackInfoAppUsage> callbackPtr {asyncCallbackInfo};
619     callbackPtr->beginTime = params.beginTime;
620     BUNDLE_ACTIVE_LOGD("QueryBundleStateInfos callbackPtr->beginTime: %{public}lld",
621         (long long)callbackPtr->beginTime);
622     callbackPtr->endTime = params.endTime;
623     BUNDLE_ACTIVE_LOGD("QueryBundleStateInfos callbackPtr->endTime: %{public}lld",
624         (long long)callbackPtr->endTime);
625     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
626     napi_value resourceName = nullptr;
627     NAPI_CALL(env, napi_create_string_latin1(env, "QueryBundleStateInfos", NAPI_AUTO_LENGTH, &resourceName));
628     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, QueryBundleStatsInfosAsync,
629         QueryBundleStatsInfosAsyncCB, static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
630     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
631     if (callbackPtr->isCallback) {
632         callbackPtr.release();
633         return BundleStateCommon::NapiGetNull(env);
634     } else {
635         callbackPtr.release();
636         return promise;
637     }
638 }
639 }  // namespace DeviceUsageStats
640 }  // namespace OHOS