• 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 <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         BundleStateCommon::DeleteNapiReference(env, params.callback);
144         return BundleStateCommon::NapiGetNull(env);
145     }
146     std::unique_ptr<AsyncQueryAppGroupCallbackInfo> callbackPtr {asyncCallbackInfo};
147     callbackPtr->bundleName = params.bundleName;
148     BUNDLE_ACTIVE_LOGD("QueryAppGroup callbackPtr->bundleName: %{public}s",
149         callbackPtr->bundleName.c_str());
150     napi_value promise = nullptr;
151     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
152     napi_value resourceName = nullptr;
153     NAPI_CALL(env, napi_create_string_latin1(env, "QueryAppGroup", NAPI_AUTO_LENGTH, &resourceName));
154     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, QueryAppGroupAsync, QueryAppGroupAsyncCB,
155         static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
156     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
157     if (callbackPtr->isCallback) {
158         callbackPtr.release();
159         return BundleStateCommon::NapiGetNull(env);
160     } else {
161         callbackPtr.release();
162         return promise;
163     }
164 }
165 
ParseQueryAppGroupSyncParameters(const napi_env & env,const napi_callback_info & info,QueryAppGroupParamsInfo & params)166 napi_value ParseQueryAppGroupSyncParameters(const napi_env &env, const napi_callback_info &info,
167     QueryAppGroupParamsInfo &params)
168 {
169     size_t argc = PRIORITY_GROUP_PARAMS;
170     napi_value argv[PRIORITY_GROUP_PARAMS] = {nullptr};
171     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
172     if ((argc != PRIORITY_GROUP_MIN_PARAMS) && (argc != PRIORITY_GROUP_MIDDLE_PARAMS)) {
173         params.errorCode = ERR_PARAMETERS_NUMBER;
174         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
175     }
176     std::string result = "";
177     params.bundleName = "";
178     if (argc == PRIORITY_GROUP_MIDDLE_PARAMS) {
179         // argv[0] : bundleName
180         params.bundleName = BundleStateCommon::GetTypeStringValue(env, argv[0], result);
181         if (params.bundleName.empty()) {
182             BUNDLE_ACTIVE_LOGE("ParseQueryAppGroupParameters failed, bundleName is empty.");
183             params.errorCode = ERR_PARAMETERS_EMPTY;
184             return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "bundleName");
185         }
186     }
187     return BundleStateCommon::NapiGetNull(env);
188 }
189 
QueryAppGroupSync(napi_env env,napi_callback_info info)190 napi_value QueryAppGroupSync(napi_env env, napi_callback_info info)
191 {
192     BUNDLE_ACTIVE_LOGI("QueryAppGroup");
193     QueryAppGroupParamsInfo params;
194     ParseQueryAppGroupSyncParameters(env, info, params);
195     int32_t priorityGroup = PRIORITY_GROUP_DEFAULT;
196     ErrCode errorCode = BundleActiveClient::GetInstance().QueryAppGroup(
197         priorityGroup, params.bundleName);
198     if (errorCode == ERR_OK) {
199         napi_value napiValue = nullptr;
200         NAPI_CALL(env, napi_create_int32(env, priorityGroup, &napiValue));
201         return napiValue;
202     }
203     return BundleStateCommon::GetErrorValue(env, errorCode);
204 }
205 
GetAppGroupParameters(const napi_env & env,napi_value * argv,ParamsBundleGroupInfo & params,size_t argvLen=0)206 napi_value GetAppGroupParameters(const napi_env &env, napi_value* argv, ParamsBundleGroupInfo &params,
207     size_t argvLen = 0)
208 {
209     if (argvLen <= FRIST_ARG) {
210         params.errorCode = ERR_PARAMETERS_EMPTY;
211         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "newGroup");
212     }
213     if (BundleStateCommon::GetInt32NumberValue(env, argv[FRIST_ARG], params.newGroup) == nullptr) {
214         BUNDLE_ACTIVE_LOGW("ParseSetAppGroupParameters failed, newGroup type is invalid.");
215         params.errorCode = ERR_NEW_GROUP_TYPE;
216         return BundleStateCommon::HandleParamErr(env, ERR_NEW_GROUP_TYPE, "");
217     }
218     bool flag = false;
219     for (const auto& item : GROUP_TYPE) {
220         if (item == params.newGroup) {
221             flag = true;
222             break;
223         }
224     }
225     if (!flag) {
226         BUNDLE_ACTIVE_LOGW("ParseSetAppGroupParameters failed, newGroup value is invalid.");
227         params.errorCode = ERR_NEW_GROUP_OUT_OF_RANGE;
228         return BundleStateCommon::HandleParamErr(env, ERR_NEW_GROUP_OUT_OF_RANGE, "");
229     }
230     return BundleStateCommon::NapiGetNull(env);
231 }
232 
GetSetAppGroupBundleName(const napi_env & env,napi_value * argv,ParamsBundleGroupInfo & params,size_t argvLen=0)233 napi_value GetSetAppGroupBundleName(const napi_env &env, napi_value* argv, ParamsBundleGroupInfo &params,
234     size_t argvLen = 0)
235 {
236     if (argvLen == ZERO_ARG) {
237         params.errorCode = ERR_PARAMETERS_EMPTY;
238         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "bundleName");
239     }
240     napi_valuetype valuetype;
241     NAPI_CALL(env, napi_typeof(env, argv[ZERO_ARG], &valuetype));
242     if (valuetype != napi_string) {
243         BUNDLE_ACTIVE_LOGW("Wrong argument type, string expected.");
244         params.errorCode = ERR_BUNDLE_NAME_TYPE;
245         return BundleStateCommon::HandleParamErr(env, ERR_BUNDLE_NAME_TYPE, "");
246     }
247     std::string result = "";
248     params.bundleName = BundleStateCommon::GetTypeStringValue(env, argv[ZERO_ARG], result);
249     if (params.bundleName.empty()) {
250         BUNDLE_ACTIVE_LOGE("ParseSetAppGroupParameters failed, bundleName is empty.");
251         params.errorCode = ERR_PARAMETERS_EMPTY;
252         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_EMPTY, "bundleName");
253     }
254     return BundleStateCommon::NapiGetNull(env);
255 }
256 
ParseSetAppGroupParameters(const napi_env & env,const napi_callback_info & info,ParamsBundleGroupInfo & params,AsyncCallbackInfoSetAppGroup * & asyncCallbackInfo)257 napi_value ParseSetAppGroupParameters(const napi_env &env, const napi_callback_info &info,
258     ParamsBundleGroupInfo &params, AsyncCallbackInfoSetAppGroup* &asyncCallbackInfo)
259 {
260     size_t argc = APP_USAGE_PARAMS_BUNDLE_GROUP;
261     napi_value argv[APP_USAGE_PARAMS_BUNDLE_GROUP] = {nullptr};
262     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
263     if ((argc != APP_USAGE_MIN_PARAMS_BUNDLE_GROUP) && (argc != APP_USAGE_PARAMS_BUNDLE_GROUP)) {
264         params.errorCode = ERR_PARAMETERS_NUMBER;
265         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
266     }
267     // argv[0] : bundleName
268     GetSetAppGroupBundleName(env, argv, params, sizeof(argv));
269     if (params.errorCode != ERR_OK) {
270         return BundleStateCommon::NapiGetNull(env);
271     }
272     // argv[1] : newGroup
273     GetAppGroupParameters(env, argv, params, sizeof(argv));
274     if (params.errorCode != ERR_OK) {
275         return BundleStateCommon::NapiGetNull(env);
276     }
277     // argv[SECOND_ARG]: callback
278     if (argc == APP_USAGE_PARAMS_BUNDLE_GROUP) {
279         napi_valuetype inputValueType = napi_undefined;
280         NAPI_CALL(env, napi_typeof(env, argv[SECOND_ARG], &inputValueType));
281         if (inputValueType != napi_function) {
282             params.errorCode = ERR_CALL_BACK_TYPE;
283             return BundleStateCommon::HandleParamErr(env, ERR_CALL_BACK_TYPE, "");
284         }
285         napi_create_reference(env, argv[SECOND_ARG], 1, &params.callback);
286     }
287     BundleStateCommon::AsyncInit(env, params, asyncCallbackInfo);
288     return BundleStateCommon::NapiGetNull(env);
289 }
290 
SetAppGroupAsync(napi_env env,void * data)291 void SetAppGroupAsync(napi_env env, void *data)
292 {
293     AsyncCallbackInfoSetAppGroup *asyncCallbackInfo = (AsyncCallbackInfoSetAppGroup *)data;
294     if (asyncCallbackInfo) {
295             asyncCallbackInfo->errorCode = BundleActiveClient::GetInstance().SetAppGroup(
296                 asyncCallbackInfo->bundleName, asyncCallbackInfo->newGroup);
297     } else {
298         BUNDLE_ACTIVE_LOGE("SetAppGroup, asyncCallbackInfo == nullptr");
299     }
300 }
301 
SetAppGroupAsyncCB(napi_env env,napi_status status,void * data)302 void SetAppGroupAsyncCB(napi_env env, napi_status status, void *data)
303 {
304     AsyncCallbackInfoSetAppGroup *asyncCallbackInfo = (AsyncCallbackInfoSetAppGroup *)data;
305     if (asyncCallbackInfo) {
306         napi_value result = nullptr;
307         napi_get_null(env, &result);
308         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
309     }
310 }
311 
SetAppGroup(napi_env env,napi_callback_info info)312 napi_value SetAppGroup(napi_env env, napi_callback_info info)
313 {
314     ParamsBundleGroupInfo params;
315     AsyncCallbackInfoSetAppGroup *asyncCallbackInfo = nullptr;
316     ParseSetAppGroupParameters(env, info, params, asyncCallbackInfo);
317     if (params.errorCode != ERR_OK && !asyncCallbackInfo) {
318         BundleStateCommon::DeleteNapiReference(env, params.callback);
319         return BundleStateCommon::NapiGetNull(env);
320     }
321     std::unique_ptr<AsyncCallbackInfoSetAppGroup> callbackPtr {asyncCallbackInfo};
322     callbackPtr->newGroup = params.newGroup;
323     callbackPtr->bundleName = params.bundleName;
324     BUNDLE_ACTIVE_LOGD("SetAppGroup, bundleName is %{public}s, newGroup is %{public}d",
325         callbackPtr->bundleName.c_str(), callbackPtr->newGroup);
326     napi_value promise = nullptr;
327     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
328     napi_value resourceName = nullptr;
329     NAPI_CALL(env, napi_create_string_latin1(env, "SetAppGroup", NAPI_AUTO_LENGTH, &resourceName));
330     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, SetAppGroupAsync, SetAppGroupAsyncCB,
331         static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
332     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
333     if (callbackPtr->isCallback) {
334         callbackPtr.release();
335         return BundleStateCommon::NapiGetNull(env);
336     } else {
337         callbackPtr.release();
338         return promise;
339     }
340 }
341 
GetAppGroupChangeCallback(const napi_env & env,const napi_value & value)342 napi_value GetAppGroupChangeCallback(const napi_env &env, const napi_value &value)
343 {
344     napi_ref result = nullptr;
345 
346     registerObserver = new (std::nothrow) AppGroupObserver();
347     if (!registerObserver) {
348         BUNDLE_ACTIVE_LOGE("RegisterAppGroupCallBack callback is null");
349         return nullptr;
350     }
351     napi_create_reference(env, value, 1, &result);
352     registerObserver->SetCallbackInfo(env, result);
353 
354     return BundleStateCommon::NapiGetNull(env);
355 }
356 
ParseRegisterAppGroupCallBackParameters(const napi_env & env,const napi_callback_info & info,RegisterCallbackInfo & params,AsyncRegisterCallbackInfo * & asyncCallbackInfo)357 napi_value ParseRegisterAppGroupCallBackParameters(const napi_env &env, const napi_callback_info &info,
358     RegisterCallbackInfo &params, AsyncRegisterCallbackInfo* &asyncCallbackInfo)
359 {
360     size_t argc = REGISTER_GROUP_CALLBACK_PARAMS;
361     napi_value argv[REGISTER_GROUP_CALLBACK_PARAMS] = {nullptr};
362     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
363     if ((argc != REGISTER_GROUP_CALLBACK_MIN_PARAMS) && (argc != REGISTER_GROUP_CALLBACK_PARAMS)) {
364         params.errorCode = ERR_PARAMETERS_NUMBER;
365         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
366     }
367 
368     // arg[0] : callback
369     napi_valuetype valuetype = napi_undefined;
370     NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
371     std::lock_guard<ffrt::mutex> lock(g_observerMutex_);
372     if (registerObserver) {
373         BUNDLE_ACTIVE_LOGI("RegisterAppGroupCallBack repeat!");
374         params.errorCode = ERR_REPEAT_REGISTER_APP_GROUP_OBSERVER;
375         return BundleStateCommon::HandleParamErr(env, ERR_REPEAT_REGISTER_APP_GROUP_OBSERVER, "");
376     } else if (valuetype != napi_function || !GetAppGroupChangeCallback(env, argv[0])) {
377         BUNDLE_ACTIVE_LOGE("RegisterAppGroupCallBack bundleActiveGroupObserverInfo parse failed");
378         params.errorCode = ERR_APP_GROUP_OBSERVER_CALLBACK_TYPE;
379         return BundleStateCommon::HandleParamErr(env, ERR_APP_GROUP_OBSERVER_CALLBACK_TYPE, "");
380     }
381 
382     // argv[1]: asyncCallback
383     if (argc == REGISTER_GROUP_CALLBACK_PARAMS) {
384         napi_valuetype inputValueType = napi_undefined;
385         NAPI_CALL(env, napi_typeof(env, argv[1], &inputValueType));
386         if (inputValueType != napi_function) {
387             params.errorCode = ERR_CALL_BACK_TYPE;
388             return BundleStateCommon::HandleParamErr(env, ERR_CALL_BACK_TYPE, "");
389         }
390         napi_create_reference(env, argv[1], 1, &params.callback);
391     }
392     BundleStateCommon::AsyncInit(env, params, asyncCallbackInfo);
393     return BundleStateCommon::NapiGetNull(env);
394 }
395 
RegisterAppGroupCallBackAsync(napi_env env,void * data)396 void RegisterAppGroupCallBackAsync(napi_env env, void *data)
397 {
398     AsyncRegisterCallbackInfo *asyncCallbackInfo = (AsyncRegisterCallbackInfo *)data;
399     if (asyncCallbackInfo) {
400         asyncCallbackInfo->errorCode =
401             BundleActiveClient::GetInstance().RegisterAppGroupCallBack(asyncCallbackInfo->observer);
402     } else {
403         BUNDLE_ACTIVE_LOGE("RegisterAppGroupCallBack, asyncCallbackInfo == nullptr");
404     }
405 }
406 
RegisterAppGroupCallBackAsyncCB(napi_env env,napi_status status,void * data)407 void RegisterAppGroupCallBackAsyncCB(napi_env env, napi_status status, void *data)
408 {
409     AsyncRegisterCallbackInfo *asyncCallbackInfo = (AsyncRegisterCallbackInfo *)data;
410     if (asyncCallbackInfo) {
411         if (asyncCallbackInfo->errorCode != ERR_OK) {
412             std::lock_guard<ffrt::mutex> lock(g_observerMutex_);
413             registerObserver = nullptr;
414         }
415         napi_value result = nullptr;
416         napi_get_null(env, &result);
417         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
418     }
419 }
420 
RegisterAppGroupCallBack(napi_env env,napi_callback_info info)421 napi_value RegisterAppGroupCallBack(napi_env env, napi_callback_info info)
422 {
423     RegisterCallbackInfo params;
424     AsyncRegisterCallbackInfo *asyncCallbackInfo = nullptr;
425     ParseRegisterAppGroupCallBackParameters(env, info, params, asyncCallbackInfo);
426     if (params.errorCode != ERR_OK && !asyncCallbackInfo) {
427         BundleStateCommon::DeleteNapiReference(env, params.callback);
428         return BundleStateCommon::NapiGetNull(env);
429     }
430     std::unique_ptr<AsyncRegisterCallbackInfo> callbackPtr {asyncCallbackInfo};
431     callbackPtr->observer = registerObserver;
432     napi_value promise = nullptr;
433     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
434     napi_value resourceName = nullptr;
435     NAPI_CALL(env, napi_create_string_latin1(env, "RegisterAppGroupCallBack", NAPI_AUTO_LENGTH, &resourceName));
436     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, RegisterAppGroupCallBackAsync,
437         RegisterAppGroupCallBackAsyncCB, static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
438     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
439     if (callbackPtr->isCallback) {
440         callbackPtr.release();
441         return BundleStateCommon::NapiGetNull(env);
442     } else {
443         callbackPtr.release();
444         return promise;
445     }
446 }
447 
ParseUnRegisterAppGroupCallBackParameters(const napi_env & env,const napi_callback_info & info,UnRegisterCallbackInfo & params,AsyncUnRegisterCallbackInfo * & asyncCallbackInfo)448 napi_value ParseUnRegisterAppGroupCallBackParameters(const napi_env &env, const napi_callback_info &info,
449     UnRegisterCallbackInfo &params, AsyncUnRegisterCallbackInfo* &asyncCallbackInfo)
450 {
451     size_t argc = UN_REGISTER_GROUP_CALLBACK_PARAMS;
452     napi_value argv[UN_REGISTER_GROUP_CALLBACK_PARAMS] = {nullptr};
453     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
454     if ((argc != UN_REGISTER_GROUP_CALLBACK_MIN_PARAMS) && (argc != UN_REGISTER_GROUP_CALLBACK_PARAMS)) {
455         params.errorCode = ERR_PARAMETERS_NUMBER;
456         return BundleStateCommon::HandleParamErr(env, ERR_PARAMETERS_NUMBER, "");
457     }
458 
459     if (argc == UN_REGISTER_GROUP_CALLBACK_PARAMS) {
460         napi_valuetype valuetype = napi_undefined;
461         NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
462         if (valuetype != napi_function) {
463             params.errorCode = ERR_CALL_BACK_TYPE;
464             return BundleStateCommon::HandleParamErr(env, ERR_CALL_BACK_TYPE, "");
465         }
466         napi_create_reference(env, argv[0], 1, &params.callback);
467     }
468     std::lock_guard<ffrt::mutex> lock(g_observerMutex_);
469     if (!registerObserver) {
470         BUNDLE_ACTIVE_LOGI("UnRegisterAppGroupCallBack observer is not exist");
471         params.errorCode = ERR_APP_GROUP_OBSERVER_IS_NULLPTR;
472         return BundleStateCommon::HandleParamErr(env, ERR_APP_GROUP_OBSERVER_IS_NULLPTR, "");
473     }
474     BundleStateCommon::AsyncInit(env, params, asyncCallbackInfo);
475     return BundleStateCommon::NapiGetNull(env);
476 }
477 
UnRegisterAppGroupCallBackAsync(napi_env env,void * data)478 void UnRegisterAppGroupCallBackAsync(napi_env env, void *data)
479 {
480     AsyncUnRegisterCallbackInfo *asyncCallbackInfo = (AsyncUnRegisterCallbackInfo *)data;
481     if (asyncCallbackInfo != nullptr) {
482         asyncCallbackInfo->errorCode =
483             BundleActiveClient::GetInstance().UnRegisterAppGroupCallBack(asyncCallbackInfo->observer);
484     } else {
485         BUNDLE_ACTIVE_LOGE("UnRegisterAppGroupCallBack, asyncCallbackInfo == nullptr");
486     }
487 }
488 
UnRegisterAppGroupCallBackAsyncCB(napi_env env,napi_status status,void * data)489 void UnRegisterAppGroupCallBackAsyncCB(napi_env env, napi_status status, void *data)
490 {
491     AsyncUnRegisterCallbackInfo *asyncCallbackInfo = (AsyncUnRegisterCallbackInfo *)data;
492     if (asyncCallbackInfo != nullptr) {
493         if (asyncCallbackInfo->errorCode == ERR_OK) {
494             std::lock_guard<ffrt::mutex> lock(g_observerMutex_);
495             registerObserver = nullptr;
496         }
497         napi_value result = nullptr;
498         napi_get_null(env, &result);
499         BundleStateCommon::GetCallbackPromiseResult(env, *asyncCallbackInfo, result);
500     }
501 }
502 
UnRegisterAppGroupCallBack(napi_env env,napi_callback_info info)503 napi_value UnRegisterAppGroupCallBack(napi_env env, napi_callback_info info)
504 {
505     UnRegisterCallbackInfo params;
506     AsyncUnRegisterCallbackInfo *asyncCallbackInfo = nullptr;
507     ParseUnRegisterAppGroupCallBackParameters(env, info, params, asyncCallbackInfo);
508     if (params.errorCode != ERR_OK && !asyncCallbackInfo) {
509         return BundleStateCommon::NapiGetNull(env);
510     }
511     std::unique_ptr<AsyncUnRegisterCallbackInfo> callbackPtr {asyncCallbackInfo};
512     callbackPtr->observer = registerObserver;
513     napi_value promise = nullptr;
514     BundleStateCommon::SettingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
515     napi_value resourceName = nullptr;
516     NAPI_CALL(env, napi_create_string_latin1(env, "UnRegisterAppGroupCallBack", NAPI_AUTO_LENGTH, &resourceName));
517     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, UnRegisterAppGroupCallBackAsync,
518         UnRegisterAppGroupCallBackAsyncCB, static_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
519     NAPI_CALL(env, napi_queue_async_work(env, callbackPtr->asyncWork));
520     if (callbackPtr->isCallback) {
521         callbackPtr.release();
522         return BundleStateCommon::NapiGetNull(env);
523     } else {
524         callbackPtr.release();
525         return promise;
526     }
527 }
528 }  // namespace DeviceUsageStats
529 }  // namespace OHOS