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 
18 #include <uv.h>
19 #include "securec.h"
20 
21 #include "bundle_active_log.h"
22 #include "bundle_state_common.h"
23 #include "bundle_state_data.h"
24 #include "bundle_state_inner_errors.h"
25 #include "app_group_callback_info.h"
26 
27 #include "bundle_active_app_group_napi.h"
28 #include "ffrt.h"
29 
30 namespace OHOS {
31 namespace DeviceUsageStats {
32 const uint32_t UN_REGISTER_GROUP_CALLBACK_MIN_PARAMS = 0;
33 const uint32_t UN_REGISTER_GROUP_CALLBACK_PARAMS = 1;
34 const uint32_t REGISTER_GROUP_CALLBACK_MIN_PARAMS = 1;
35 const uint32_t REGISTER_GROUP_CALLBACK_PARAMS = 2;
36 const uint32_t PRIORITY_GROUP_MIN_PARAMS = 0;
37 const uint32_t PRIORITY_GROUP_MIDDLE_PARAMS = 1;
38 const uint32_t PRIORITY_GROUP_PARAMS = 2;
39 const int32_t PRIORITY_GROUP_DEFAULT = -1;
40 const uint32_t APP_USAGE_MIN_PARAMS_BUNDLE_GROUP = 2;
41 const uint32_t APP_USAGE_PARAMS_BUNDLE_GROUP = 3;
42 const uint32_t ZERO_ARG = 0;
43 const uint32_t FRIST_ARG = 1;
44 const uint32_t SECOND_ARG = 2;
45 const std::vector<int32_t> GROUP_TYPE {10, 20, 30, 40, 50, 60};
46 
47 static sptr<AppGroupObserver> registerObserver = nullptr;
48 ffrt::mutex g_observerMutex_;
49 
GetQueryAppGroupBundleName(const napi_env & env,napi_value * argv,QueryAppGroupParamsInfo & params,size_t argvLen=0)50 napi_value GetQueryAppGroupBundleName(const napi_env &env, napi_value* argv, QueryAppGroupParamsInfo &params,
51     size_t argvLen = 0)
52 {
53     if (argvLen == ZERO_ARG) {
54         params.errorCode = ERR_PARAMETERS_EMPTY;
55         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "bundleName");
56     }
57     napi_valuetype valuetype;
58     NAPI_CALL(env, napi_typeof(env, argv[ZERO_ARG], &valuetype));
59     if (valuetype != napi_string) {
60         BUNDLE_ACTIVE_LOGW("Wrong argument type, string expected.");
61         params.errorCode = ERR_BUNDLE_NAME_TYPE;
62         return BundleStateCommon::HandleParamErr(env, ERR_BUNDLE_NAME_TYPE, "");
63     }
64     std::string result = "";
65     params.bundleName = BundleStateCommon::GetTypeStringValue(env, argv[ZERO_ARG], result);
66     if (params.bundleName.empty()) {
67         BUNDLE_ACTIVE_LOGW("ParseSetAppGroupParameters failed, bundleName is empty.");
68         params.errorCode = ERR_PARAMETERS_EMPTY;
69         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "bundleName");
70     }
71     return BundleStateCommon::NapiGetNull(env);
72 }
73 
ParseQueryAppGroupParameters(const napi_env & env,const napi_callback_info & info,QueryAppGroupParamsInfo & params,AsyncQueryAppGroupCallbackInfo * & asyncCallbackInfo)74 napi_value ParseQueryAppGroupParameters(const napi_env &env, const napi_callback_info &info,
75     QueryAppGroupParamsInfo &params, AsyncQueryAppGroupCallbackInfo* &asyncCallbackInfo)
76 {
77     size_t argc = PRIORITY_GROUP_PARAMS;
78     napi_value argv[PRIORITY_GROUP_PARAMS] = {nullptr};
79     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
80     if ((argc != PRIORITY_GROUP_MIN_PARAMS) && (argc != PRIORITY_GROUP_MIDDLE_PARAMS) &&
81         (argc != PRIORITY_GROUP_PARAMS)) {
82         params.errorCode = ERR_PARAMETERS_NUMBER;
83         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
84     }
85     params.bundleName = "";
86     if (argc == PRIORITY_GROUP_MIDDLE_PARAMS) {
87         napi_valuetype valuetype = napi_undefined;
88         NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
89         if (valuetype == napi_function) {
90             napi_create_reference(env, argv[0], 1, &params.callback);
91         } else {
92             GetQueryAppGroupBundleName(env, argv, params, sizeof(argv));
93             if (params.errorCode != ERR_OK) {
94                 return BundleStateCommon::NapiGetNull(env);
95             }
96         }
97     } else if (argc == PRIORITY_GROUP_PARAMS) {
98         // argv[0] : bundleName
99         GetQueryAppGroupBundleName(env, argv, params, sizeof(argv));
100         if (params.errorCode != ERR_OK) {
101             return BundleStateCommon::NapiGetNull(env);
102         }
103         // argv[1]: callback
104         napi_valuetype inputValueType = napi_undefined;
105         NAPI_CALL(env, napi_typeof(env, argv[1], &inputValueType));
106         if (inputValueType != napi_function) {
107             params.errorCode = ERR_CALL_BACK_TYPE;
108             return BundleStateCommon::HandleParamErr(env, ERR_CALL_BACK_TYPE, "");
109         }
110         napi_create_reference(env, argv[1], 1, &params.callback);
111     }
112     BundleStateCommon::AsyncInit(env, params, asyncCallbackInfo);
113     return BundleStateCommon::NapiGetNull(env);
114 }
115 
QueryAppGroupAsync(napi_env env,void * data)116 void QueryAppGroupAsync(napi_env env, void *data)
117 {
118     AsyncQueryAppGroupCallbackInfo *asyncCallbackInfo = (AsyncQueryAppGroupCallbackInfo *)data;
119     if (asyncCallbackInfo) {
120         asyncCallbackInfo->errorCode = BundleActiveClient::GetInstance().QueryAppGroup(
121             asyncCallbackInfo->priorityGroup, asyncCallbackInfo->bundleName);
122     } else {
123         BUNDLE_ACTIVE_LOGE("QueryAppGroup, asyncCallbackInfo == nullptr");
124     }
125 }
126 
QueryAppGroupAsyncCB(napi_env env,napi_status status,void * data)127 void QueryAppGroupAsyncCB(napi_env env, napi_status status, void *data)
128 {
129     AsyncQueryAppGroupCallbackInfo *asyncCallbackInfo = (AsyncQueryAppGroupCallbackInfo *)data;
130     if (asyncCallbackInfo) {
131         napi_value result = nullptr;
132         napi_create_int32(env, asyncCallbackInfo->priorityGroup, &result);
133         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
134     }
135 }
136 
QueryAppGroup(napi_env env,napi_callback_info info)137 napi_value QueryAppGroup(napi_env env, napi_callback_info info)
138 {
139     QueryAppGroupParamsInfo params;
140     AsyncQueryAppGroupCallbackInfo *asyncCallbackInfo = nullptr;
141     ParseQueryAppGroupParameters(env, info, params, asyncCallbackInfo);
142     if (params.errorCode != ERR_OK && !asyncCallbackInfo) {
143         return BundleStateCommon::NapiGetNull(env);
144     }
145     std::unique_ptr<AsyncQueryAppGroupCallbackInfo> callbackPtr {asyncCallbackInfo};
146     callbackPtr->bundleName = params.bundleName;
147     BUNDLE_ACTIVE_LOGD("QueryAppGroup callbackPtr->bundleName: %{public}s",
148         callbackPtr->bundleName.c_str());
149     napi_value promise = nullptr;
150     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
151     napi_value resourceName = nullptr;
152     NAPI_CALL(env, napi_create_string_latin1(env, "QueryAppGroup", NAPI_AUTO_LENGTH, &resourceName));
153     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, QueryAppGroupAsync, QueryAppGroupAsyncCB,
154         static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
155     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
156     if (callbackPtr->isCallback) {
157         callbackPtr.release();
158         return BundleStateCommon::NapiGetNull(env);
159     } else {
160         callbackPtr.release();
161         return promise;
162     }
163 }
164 
ParseQueryAppGroupSyncParameters(const napi_env & env,const napi_callback_info & info,QueryAppGroupParamsInfo & params)165 napi_value ParseQueryAppGroupSyncParameters(const napi_env &env, const napi_callback_info &info,
166     QueryAppGroupParamsInfo &params)
167 {
168     size_t argc = PRIORITY_GROUP_PARAMS;
169     napi_value argv[PRIORITY_GROUP_PARAMS] = {nullptr};
170     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
171     if ((argc != PRIORITY_GROUP_MIN_PARAMS) && (argc != PRIORITY_GROUP_MIDDLE_PARAMS)) {
172         params.errorCode = ERR_PARAMETERS_NUMBER;
173         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
174     }
175     std::string result = "";
176     params.bundleName = "";
177     if (argc == PRIORITY_GROUP_MIDDLE_PARAMS) {
178         // argv[0] : bundleName
179         params.bundleName = BundleStateCommon::GetTypeStringValue(env, argv[0], result);
180         if (params.bundleName.empty()) {
181             BUNDLE_ACTIVE_LOGE("ParseQueryAppGroupParameters failed, bundleName is empty.");
182             params.errorCode = ERR_PARAMETERS_EMPTY;
183             return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "bundleName");
184         }
185     }
186     return BundleStateCommon::NapiGetNull(env);
187 }
188 
QueryAppGroupSync(napi_env env,napi_callback_info info)189 napi_value QueryAppGroupSync(napi_env env, napi_callback_info info)
190 {
191     BUNDLE_ACTIVE_LOGI("QueryAppGroup");
192     QueryAppGroupParamsInfo params;
193     ParseQueryAppGroupSyncParameters(env, info, params);
194     int32_t priorityGroup = PRIORITY_GROUP_DEFAULT;
195     ErrCode errorCode = BundleActiveClient::GetInstance().QueryAppGroup(
196         priorityGroup, params.bundleName);
197     if (errorCode == ERR_OK) {
198         napi_value napiValue = nullptr;
199         NAPI_CALL(env, napi_create_int32(env, priorityGroup, &napiValue));
200         return napiValue;
201     }
202     return BundleStateCommon::GetErrorValue(env, errorCode);
203 }
204 
GetAppGroupParameters(const napi_env & env,napi_value * argv,ParamsBundleGroupInfo & params,size_t argvLen=0)205 napi_value GetAppGroupParameters(const napi_env &env, napi_value* argv, ParamsBundleGroupInfo &params,
206     size_t argvLen = 0)
207 {
208     if (argvLen <= FRIST_ARG) {
209         params.errorCode = ERR_PARAMETERS_EMPTY;
210         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "newGroup");
211     }
212     if (BundleStateCommon::GetInt32NumberValue(env, argv[FRIST_ARG], params.newGroup) == nullptr) {
213         BUNDLE_ACTIVE_LOGW("ParseSetAppGroupParameters failed, newGroup type is invalid.");
214         params.errorCode = ERR_NEW_GROUP_TYPE;
215         return BundleStateCommon::HandleParamErr(env, ERR_NEW_GROUP_TYPE, "");
216     }
217     bool flag = false;
218     for (const auto& item : GROUP_TYPE) {
219         if (item == params.newGroup) {
220             flag = true;
221             break;
222         }
223     }
224     if (!flag) {
225         BUNDLE_ACTIVE_LOGW("ParseSetAppGroupParameters failed, newGroup value is invalid.");
226         params.errorCode = ERR_NEW_GROUP_OUT_OF_RANGE;
227         return BundleStateCommon::HandleParamErr(env, ERR_NEW_GROUP_OUT_OF_RANGE, "");
228     }
229     return BundleStateCommon::NapiGetNull(env);
230 }
231 
GetSetAppGroupBundleName(const napi_env & env,napi_value * argv,ParamsBundleGroupInfo & params,size_t argvLen=0)232 napi_value GetSetAppGroupBundleName(const napi_env &env, napi_value* argv, ParamsBundleGroupInfo &params,
233     size_t argvLen = 0)
234 {
235     if (argvLen == ZERO_ARG) {
236         params.errorCode = ERR_PARAMETERS_EMPTY;
237         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "bundleName");
238     }
239     napi_valuetype valuetype;
240     NAPI_CALL(env, napi_typeof(env, argv[ZERO_ARG], &valuetype));
241     if (valuetype != napi_string) {
242         BUNDLE_ACTIVE_LOGW("Wrong argument type, string expected.");
243         params.errorCode = ERR_BUNDLE_NAME_TYPE;
244         return BundleStateCommon::HandleParamErr(env, ERR_BUNDLE_NAME_TYPE, "");
245     }
246     std::string result = "";
247     params.bundleName = BundleStateCommon::GetTypeStringValue(env, argv[ZERO_ARG], result);
248     if (params.bundleName.empty()) {
249         BUNDLE_ACTIVE_LOGE("ParseSetAppGroupParameters failed, bundleName is empty.");
250         params.errorCode = ERR_PARAMETERS_EMPTY;
251         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "bundleName");
252     }
253     return BundleStateCommon::NapiGetNull(env);
254 }
255 
ParseSetAppGroupParameters(const napi_env & env,const napi_callback_info & info,ParamsBundleGroupInfo & params,AsyncCallbackInfoSetAppGroup * & asyncCallbackInfo)256 napi_value ParseSetAppGroupParameters(const napi_env &env, const napi_callback_info &info,
257     ParamsBundleGroupInfo &params, AsyncCallbackInfoSetAppGroup* &asyncCallbackInfo)
258 {
259     size_t argc = APP_USAGE_PARAMS_BUNDLE_GROUP;
260     napi_value argv[APP_USAGE_PARAMS_BUNDLE_GROUP] = {nullptr};
261     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
262     if ((argc != APP_USAGE_MIN_PARAMS_BUNDLE_GROUP) && (argc != APP_USAGE_PARAMS_BUNDLE_GROUP)) {
263         params.errorCode = ERR_PARAMETERS_NUMBER;
264         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
265     }
266     // argv[0] : bundleName
267     GetSetAppGroupBundleName(env, argv, params, sizeof(argv));
268     if (params.errorCode != ERR_OK) {
269         return BundleStateCommon::NapiGetNull(env);
270     }
271     // argv[1] : newGroup
272     GetAppGroupParameters(env, argv, params, sizeof(argv));
273     if (params.errorCode != ERR_OK) {
274         return BundleStateCommon::NapiGetNull(env);
275     }
276     // argv[SECOND_ARG]: callback
277     if (argc == APP_USAGE_PARAMS_BUNDLE_GROUP) {
278         napi_valuetype inputValueType = napi_undefined;
279         NAPI_CALL(env, napi_typeof(env, argv[SECOND_ARG], &inputValueType));
280         if (inputValueType != napi_function) {
281             params.errorCode = ERR_CALL_BACK_TYPE;
282             return BundleStateCommon::HandleParamErr(env, ERR_CALL_BACK_TYPE, "");
283         }
284         napi_create_reference(env, argv[SECOND_ARG], 1, &params.callback);
285     }
286     BundleStateCommon::AsyncInit(env, params, asyncCallbackInfo);
287     return BundleStateCommon::NapiGetNull(env);
288 }
289 
SetAppGroupAsync(napi_env env,void * data)290 void SetAppGroupAsync(napi_env env, void *data)
291 {
292     AsyncCallbackInfoSetAppGroup *asyncCallbackInfo = (AsyncCallbackInfoSetAppGroup *)data;
293     if (asyncCallbackInfo) {
294             asyncCallbackInfo->errorCode = BundleActiveClient::GetInstance().SetAppGroup(
295                 asyncCallbackInfo->bundleName, asyncCallbackInfo->newGroup);
296     } else {
297         BUNDLE_ACTIVE_LOGE("SetAppGroup, asyncCallbackInfo == nullptr");
298     }
299 }
300 
SetAppGroupAsyncCB(napi_env env,napi_status status,void * data)301 void SetAppGroupAsyncCB(napi_env env, napi_status status, void *data)
302 {
303     AsyncCallbackInfoSetAppGroup *asyncCallbackInfo = (AsyncCallbackInfoSetAppGroup *)data;
304     if (asyncCallbackInfo) {
305         napi_value result = nullptr;
306         napi_get_null(env, &result);
307         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
308     }
309 }
310 
SetAppGroup(napi_env env,napi_callback_info info)311 napi_value SetAppGroup(napi_env env, napi_callback_info info)
312 {
313     ParamsBundleGroupInfo params;
314     AsyncCallbackInfoSetAppGroup *asyncCallbackInfo = nullptr;
315     ParseSetAppGroupParameters(env, info, params, asyncCallbackInfo);
316     if (params.errorCode != ERR_OK && !asyncCallbackInfo) {
317         return BundleStateCommon::NapiGetNull(env);
318     }
319     std::unique_ptr<AsyncCallbackInfoSetAppGroup> callbackPtr {asyncCallbackInfo};
320     callbackPtr->newGroup = params.newGroup;
321     callbackPtr->bundleName = params.bundleName;
322     BUNDLE_ACTIVE_LOGD("SetAppGroup, bundleName is %{public}s, newGroup is %{public}d",
323         callbackPtr->bundleName.c_str(), callbackPtr->newGroup);
324     napi_value promise = nullptr;
325     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
326     napi_value resourceName = nullptr;
327     NAPI_CALL(env, napi_create_string_latin1(env, "SetAppGroup", NAPI_AUTO_LENGTH, &resourceName));
328     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, SetAppGroupAsync, SetAppGroupAsyncCB,
329         static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
330     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
331     if (callbackPtr->isCallback) {
332         callbackPtr.release();
333         return BundleStateCommon::NapiGetNull(env);
334     } else {
335         callbackPtr.release();
336         return promise;
337     }
338 }
339 
GetAppGroupChangeCallback(const napi_env & env,const napi_value & value)340 napi_value GetAppGroupChangeCallback(const napi_env &env, const napi_value &value)
341 {
342     napi_ref result = nullptr;
343 
344     registerObserver = new (std::nothrow) AppGroupObserver();
345     if (!registerObserver) {
346         BUNDLE_ACTIVE_LOGE("RegisterAppGroupCallBack callback is null");
347         return nullptr;
348     }
349     napi_create_reference(env, value, 1, &result);
350     registerObserver->SetCallbackInfo(env, result);
351 
352     return BundleStateCommon::NapiGetNull(env);
353 }
354 
ParseRegisterAppGroupCallBackParameters(const napi_env & env,const napi_callback_info & info,RegisterCallbackInfo & params,AsyncRegisterCallbackInfo * & asyncCallbackInfo)355 napi_value ParseRegisterAppGroupCallBackParameters(const napi_env &env, const napi_callback_info &info,
356     RegisterCallbackInfo &params, AsyncRegisterCallbackInfo* &asyncCallbackInfo)
357 {
358     size_t argc = REGISTER_GROUP_CALLBACK_PARAMS;
359     napi_value argv[REGISTER_GROUP_CALLBACK_PARAMS] = {nullptr};
360     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
361     if ((argc != REGISTER_GROUP_CALLBACK_MIN_PARAMS) && (argc != REGISTER_GROUP_CALLBACK_PARAMS)) {
362         params.errorCode = ERR_PARAMETERS_NUMBER;
363         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
364     }
365 
366     // arg[0] : callback
367     napi_valuetype valuetype = napi_undefined;
368     NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
369     std::lock_guard<ffrt::mutex> lock(g_observerMutex_);
370     if (registerObserver) {
371         BUNDLE_ACTIVE_LOGI("RegisterAppGroupCallBack repeat!");
372         params.errorCode = ERR_REPEAT_REGISTER_APP_GROUP_OBSERVER;
373         return BundleStateCommon::HandleParamErr(env, ERR_REPEAT_REGISTER_APP_GROUP_OBSERVER, "");
374     } else if (valuetype != napi_function || !GetAppGroupChangeCallback(env, argv[0])) {
375         BUNDLE_ACTIVE_LOGE("RegisterAppGroupCallBack bundleActiveGroupObserverInfo parse failed");
376         params.errorCode = ERR_APP_GROUP_OBSERVER_CALLBACK_TYPE;
377         return BundleStateCommon::HandleParamErr(env, ERR_APP_GROUP_OBSERVER_CALLBACK_TYPE, "");
378     }
379 
380     // argv[1]: asyncCallback
381     if (argc == REGISTER_GROUP_CALLBACK_PARAMS) {
382         napi_valuetype inputValueType = napi_undefined;
383         NAPI_CALL(env, napi_typeof(env, argv[1], &inputValueType));
384         if (inputValueType != napi_function) {
385             params.errorCode = ERR_CALL_BACK_TYPE;
386             return BundleStateCommon::HandleParamErr(env, ERR_CALL_BACK_TYPE, "");
387         }
388         napi_create_reference(env, argv[1], 1, &params.callback);
389     }
390     BundleStateCommon::AsyncInit(env, params, asyncCallbackInfo);
391     return BundleStateCommon::NapiGetNull(env);
392 }
393 
RegisterAppGroupCallBackAsync(napi_env env,void * data)394 void RegisterAppGroupCallBackAsync(napi_env env, void *data)
395 {
396     AsyncRegisterCallbackInfo *asyncCallbackInfo = (AsyncRegisterCallbackInfo *)data;
397     if (asyncCallbackInfo) {
398         asyncCallbackInfo->errorCode =
399             BundleActiveClient::GetInstance().RegisterAppGroupCallBack(asyncCallbackInfo->observer);
400     } else {
401         BUNDLE_ACTIVE_LOGE("RegisterAppGroupCallBack, asyncCallbackInfo == nullptr");
402     }
403 }
404 
RegisterAppGroupCallBackAsyncCB(napi_env env,napi_status status,void * data)405 void RegisterAppGroupCallBackAsyncCB(napi_env env, napi_status status, void *data)
406 {
407     AsyncRegisterCallbackInfo *asyncCallbackInfo = (AsyncRegisterCallbackInfo *)data;
408     if (asyncCallbackInfo) {
409         if (asyncCallbackInfo->errorCode != ERR_OK) {
410             std::lock_guard<ffrt::mutex> lock(g_observerMutex_);
411             registerObserver = nullptr;
412         }
413         napi_value result = nullptr;
414         napi_get_null(env, &result);
415         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
416     }
417 }
418 
RegisterAppGroupCallBack(napi_env env,napi_callback_info info)419 napi_value RegisterAppGroupCallBack(napi_env env, napi_callback_info info)
420 {
421     RegisterCallbackInfo params;
422     AsyncRegisterCallbackInfo *asyncCallbackInfo = nullptr;
423     ParseRegisterAppGroupCallBackParameters(env, info, params, asyncCallbackInfo);
424     if (params.errorCode != ERR_OK && !asyncCallbackInfo) {
425         // return BundleStateCommon::JSParaError(env, params.callback, params.errorCode);
426         return BundleStateCommon::NapiGetNull(env);
427     }
428     std::unique_ptr<AsyncRegisterCallbackInfo> callbackPtr {asyncCallbackInfo};
429     callbackPtr->observer = registerObserver;
430     napi_value promise = nullptr;
431     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
432     napi_value resourceName = nullptr;
433     NAPI_CALL(env, napi_create_string_latin1(env, "RegisterAppGroupCallBack", NAPI_AUTO_LENGTH, &resourceName));
434     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, RegisterAppGroupCallBackAsync,
435         RegisterAppGroupCallBackAsyncCB, static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
436     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
437     if (callbackPtr->isCallback) {
438         callbackPtr.release();
439         return BundleStateCommon::NapiGetNull(env);
440     } else {
441         callbackPtr.release();
442         return promise;
443     }
444 }
445 
ParseUnRegisterAppGroupCallBackParameters(const napi_env & env,const napi_callback_info & info,UnRegisterCallbackInfo & params,AsyncUnRegisterCallbackInfo * & asyncCallbackInfo)446 napi_value ParseUnRegisterAppGroupCallBackParameters(const napi_env &env, const napi_callback_info &info,
447     UnRegisterCallbackInfo &params, AsyncUnRegisterCallbackInfo* &asyncCallbackInfo)
448 {
449     size_t argc = UN_REGISTER_GROUP_CALLBACK_PARAMS;
450     napi_value argv[UN_REGISTER_GROUP_CALLBACK_PARAMS] = {nullptr};
451     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
452     if ((argc != UN_REGISTER_GROUP_CALLBACK_MIN_PARAMS) && (argc != UN_REGISTER_GROUP_CALLBACK_PARAMS)) {
453         params.errorCode = ERR_PARAMETERS_NUMBER;
454         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
455     }
456 
457     if (argc == UN_REGISTER_GROUP_CALLBACK_PARAMS) {
458         napi_valuetype valuetype = napi_undefined;
459         NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
460         if (valuetype != napi_function) {
461             params.errorCode = ERR_CALL_BACK_TYPE;
462             return BundleStateCommon::HandleParamErr(env, ERR_CALL_BACK_TYPE, "");
463         }
464         napi_create_reference(env, argv[0], 1, &params.callback);
465     }
466     std::lock_guard<ffrt::mutex> lock(g_observerMutex_);
467     if (!registerObserver) {
468         BUNDLE_ACTIVE_LOGI("UnRegisterAppGroupCallBack observer is not exist");
469         params.errorCode = ERR_APP_GROUP_OBSERVER_IS_NULLPTR;
470         return BundleStateCommon::HandleParamErr(env, ERR_APP_GROUP_OBSERVER_IS_NULLPTR, "");
471     }
472     BundleStateCommon::AsyncInit(env, params, asyncCallbackInfo);
473     return BundleStateCommon::NapiGetNull(env);
474 }
475 
UnRegisterAppGroupCallBackAsync(napi_env env,void * data)476 void UnRegisterAppGroupCallBackAsync(napi_env env, void *data)
477 {
478     AsyncUnRegisterCallbackInfo *asyncCallbackInfo = (AsyncUnRegisterCallbackInfo *)data;
479     if (asyncCallbackInfo != nullptr) {
480         asyncCallbackInfo->errorCode =
481             BundleActiveClient::GetInstance().UnRegisterAppGroupCallBack(asyncCallbackInfo->observer);
482     } else {
483         BUNDLE_ACTIVE_LOGE("UnRegisterAppGroupCallBack, asyncCallbackInfo == nullptr");
484     }
485 }
486 
UnRegisterAppGroupCallBackAsyncCB(napi_env env,napi_status status,void * data)487 void UnRegisterAppGroupCallBackAsyncCB(napi_env env, napi_status status, void *data)
488 {
489     AsyncUnRegisterCallbackInfo *asyncCallbackInfo = (AsyncUnRegisterCallbackInfo *)data;
490     if (asyncCallbackInfo != nullptr) {
491         if (asyncCallbackInfo->errorCode == ERR_OK) {
492             std::lock_guard<ffrt::mutex> lock(g_observerMutex_);
493             registerObserver = nullptr;
494         }
495         napi_value result = nullptr;
496         napi_get_null(env, &result);
497         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
498     }
499 }
500 
UnRegisterAppGroupCallBack(napi_env env,napi_callback_info info)501 napi_value UnRegisterAppGroupCallBack(napi_env env, napi_callback_info info)
502 {
503     UnRegisterCallbackInfo params;
504     AsyncUnRegisterCallbackInfo *asyncCallbackInfo = nullptr;
505     ParseUnRegisterAppGroupCallBackParameters(env, info, params, asyncCallbackInfo);
506     if (params.errorCode != ERR_OK && !asyncCallbackInfo) {
507         return BundleStateCommon::NapiGetNull(env);
508     }
509     std::unique_ptr<AsyncUnRegisterCallbackInfo> callbackPtr {asyncCallbackInfo};
510     callbackPtr->observer = registerObserver;
511     napi_value promise = nullptr;
512     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
513     napi_value resourceName = nullptr;
514     NAPI_CALL(env, napi_create_string_latin1(env, "UnRegisterAppGroupCallBack", NAPI_AUTO_LENGTH, &resourceName));
515     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, UnRegisterAppGroupCallBackAsync,
516         UnRegisterAppGroupCallBackAsyncCB, static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
517     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
518     if (callbackPtr->isCallback) {
519         callbackPtr.release();
520         return BundleStateCommon::NapiGetNull(env);
521     } else {
522         callbackPtr.release();
523         return promise;
524     }
525 }
526 }  // namespace DeviceUsageStats
527 }  // namespace OHOS