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 "location_napi_adapter.h"
17 #include "location_log.h"
18 #include "location_napi_errcode.h"
19 #include "constant_definition.h"
20 #include "geofence_sdk.h"
21 #include "geofence_napi.h"
22 #include "geofence_async_context.h"
23 
24 namespace OHOS {
25 namespace Location {
26 auto g_locatorClient = Locator::GetInstance();
27 auto g_geofenceClient = GeofenceManager::GetInstance();
28 std::map<int, sptr<LocationGnssGeofenceCallbackNapi>> g_gnssGeofenceCallbackHostMap;
29 std::mutex g_gnssGeofenceCallbackHostMutex;
30 
GetLastLocation(napi_env env,napi_callback_info info)31 napi_value GetLastLocation(napi_env env, napi_callback_info info)
32 {
33     size_t argc = MAXIMUM_JS_PARAMS;
34     napi_value argv[MAXIMUM_JS_PARAMS];
35     napi_value thisVar = nullptr;
36     void* data = nullptr;
37 
38     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
39     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
40 
41 #ifdef ENABLE_NAPI_MANAGER
42     return HandleGetCachedLocation(env);
43 #else
44     auto asyncContext = new (std::nothrow) LocationAsyncContext(env);
45     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
46     NAPI_CALL(env, napi_create_string_latin1(env, "getLastLocation", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
47     asyncContext->executeFunc = [&](void* data) -> void {
48         auto context = static_cast<LocationAsyncContext*>(data);
49         context->loc = g_locatorClient->IsLocationEnabled() ? g_locatorClient->GetCachedLocation() : nullptr;
50         if (context->loc != nullptr) {
51             context->errCode = SUCCESS;
52         } else {
53             context->errCode = LAST_KNOWN_LOCATION_ERROR;
54         }
55     };
56 
57     asyncContext->completeFunc = [&](void* data) -> void {
58         auto context = static_cast<LocationAsyncContext*>(data);
59         NAPI_CALL_RETURN_VOID(context->env, napi_create_object(context->env, &context->result[PARAM1]));
60         if (context->loc != nullptr) {
61             LocationToJs(context->env, context->loc, context->result[PARAM1]);
62         } else {
63             LBSLOGE(LOCATOR_STANDARD, "loc is nullptr!");
64         }
65         LBSLOGI(LOCATOR_STANDARD, "Push last location result to client");
66     };
67 
68     size_t objectArgsNum = 0;
69     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
70 #endif
71 }
72 
73 #ifdef ENABLE_NAPI_MANAGER
HandleGetCachedLocation(napi_env env)74 napi_value HandleGetCachedLocation(napi_env env)
75 {
76     napi_value res;
77     NAPI_CALL(env, napi_create_object(env, &res));
78     LocationErrCode errorCode = CheckLocationSwitchState();
79     if (errorCode != ERRCODE_SUCCESS) {
80         HandleSyncErrCode(env, errorCode);
81         return UndefinedNapiValue(env);
82     }
83     std::unique_ptr<Location> loc;
84     errorCode = g_locatorClient->GetCachedLocationV9(loc);
85     if (loc != nullptr) {
86         LocationToJs(env, loc, res);
87         return res;
88     } else {
89         HandleSyncErrCode(env, errorCode);
90     }
91     return UndefinedNapiValue(env);
92 }
93 #endif
94 
IsLocationEnabled(napi_env env,napi_callback_info info)95 napi_value IsLocationEnabled(napi_env env, napi_callback_info info)
96 {
97     size_t argc = MAXIMUM_JS_PARAMS;
98     napi_value argv[MAXIMUM_JS_PARAMS];
99     napi_value thisVar = nullptr;
100     void* data = nullptr;
101     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
102     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
103 #ifdef ENABLE_NAPI_MANAGER
104     napi_value res;
105     bool isEnabled = false;
106     LocationErrCode errorCode = g_locatorClient->IsLocationEnabledV9(isEnabled);
107     if (errorCode != ERRCODE_SUCCESS) {
108         HandleSyncErrCode(env, errorCode);
109         return UndefinedNapiValue(env);
110     }
111     NAPI_CALL(env, napi_get_boolean(env, isEnabled, &res));
112     return res;
113 #else
114     auto asyncContext = new (std::nothrow) SwitchAsyncContext(env);
115     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
116     if (napi_create_string_latin1(env, "isLocationEnabled", NAPI_AUTO_LENGTH,
117         &asyncContext->resourceName) != napi_ok) {
118         LBSLOGE(LOCATOR_STANDARD, "copy string failed");
119     }
120     asyncContext->executeFunc = [&](void* data) -> void {
121         auto context = static_cast<SwitchAsyncContext*>(data);
122         context->enable = g_locatorClient->IsLocationEnabled();
123         context->errCode = SUCCESS;
124     };
125     asyncContext->completeFunc = [&](void* data) -> void {
126         auto context = static_cast<SwitchAsyncContext*>(data);
127         NAPI_CALL_RETURN_VOID(context->env, napi_get_boolean(context->env, context->enable, &context->result[PARAM1]));
128         LBSLOGI(LOCATOR_STANDARD, "Push IsLocationEnabled result to client");
129     };
130 
131     size_t objectArgsNum = 0;
132     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
133 #endif
134 }
135 
136 #ifdef ENABLE_NAPI_MANAGER
GetCurrentWifiBssidForLocating(napi_env env,napi_callback_info info)137 napi_value GetCurrentWifiBssidForLocating(napi_env env, napi_callback_info info)
138 {
139     size_t argc = MAXIMUM_JS_PARAMS;
140     napi_value argv[MAXIMUM_JS_PARAMS];
141     napi_value thisVar = nullptr;
142     void* data = nullptr;
143     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
144     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
145     napi_value res;
146     std::string bssid;
147     LocationErrCode errorCode = g_locatorClient->GetCurrentWifiBssidForLocating(bssid);
148     if (errorCode != ERRCODE_SUCCESS) {
149         HandleSyncErrCode(env, errorCode);
150         return UndefinedNapiValue(env);
151     }
152     NAPI_CALL(env, napi_create_string_utf8(env, bssid.c_str(), NAPI_AUTO_LENGTH, &res));
153     return res;
154 }
155 #endif
156 
EnableLocation(napi_env env,napi_callback_info info)157 napi_value EnableLocation(napi_env env, napi_callback_info info)
158 {
159     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
160     size_t argc = MAXIMUM_JS_PARAMS;
161     napi_value argv[MAXIMUM_JS_PARAMS];
162     napi_value thisVar = nullptr;
163     void* data = nullptr;
164     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
165     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
166 #ifdef ENABLE_NAPI_MANAGER
167     if (argc > PARAM1 || (argc == PARAM1 && !CheckIfParamIsFunctionType(env, argv[PARAM0]))) {
168         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
169         return UndefinedNapiValue(env);
170     }
171 #endif
172     auto asyncContext = new (std::nothrow) SwitchAsyncContext(env);
173     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
174     NAPI_CALL(env, napi_create_string_latin1(env, "enableLocation", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
175 
176     asyncContext->executeFunc = [&](void* data) -> void {
177         auto context = static_cast<SwitchAsyncContext*>(data);
178 #ifdef ENABLE_NAPI_MANAGER
179         context->errCode = g_locatorClient->EnableAbilityV9(true);
180 #else
181         g_locatorClient->EnableAbility(true);
182         context->errCode = SUCCESS;
183 #endif
184     };
185 
186     asyncContext->completeFunc = [&](void* data) -> void {
187         auto context = static_cast<SwitchAsyncContext*>(data);
188 #ifdef ENABLE_NAPI_MANAGER
189         NAPI_CALL_RETURN_VOID(context->env, napi_get_undefined(context->env, &context->result[PARAM1]));
190 #else
191         NAPI_CALL_RETURN_VOID(context->env,
192             napi_get_boolean(context->env, context->errCode == SUCCESS, &context->result[PARAM1]));
193 #endif
194         LBSLOGI(LOCATOR_STANDARD, "Push EnableLocation result to client");
195     };
196 
197     size_t objectArgsNum = 0;
198     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
199 }
200 
DisableLocation(napi_env env,napi_callback_info info)201 napi_value DisableLocation(napi_env env, napi_callback_info info)
202 {
203     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
204     size_t argc = MAXIMUM_JS_PARAMS;
205     napi_value argv[MAXIMUM_JS_PARAMS];
206     napi_value thisVar = nullptr;
207     void* data = nullptr;
208     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
209     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
210 
211 #ifdef ENABLE_NAPI_MANAGER
212     LocationErrCode errorCode = g_locatorClient->EnableAbilityV9(false);
213     if (errorCode != ERRCODE_SUCCESS) {
214         HandleSyncErrCode(env, errorCode);
215     }
216     return UndefinedNapiValue(env);
217 #else
218     auto asyncContext = new (std::nothrow) SwitchAsyncContext(env);
219     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
220     NAPI_CALL(env, napi_create_string_latin1(env, "disableLocation", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
221     asyncContext->executeFunc = [&](void* data) -> void {
222         auto context = static_cast<SwitchAsyncContext*>(data);
223         g_locatorClient->EnableAbility(false);
224         context->errCode = SUCCESS;
225     };
226     asyncContext->completeFunc = [&](void* data) -> void {
227         auto context = static_cast<SwitchAsyncContext*>(data);
228         NAPI_CALL_RETURN_VOID(context->env,
229             napi_get_boolean(context->env, context->errCode == SUCCESS, &context->result[PARAM1]));
230         LBSLOGI(LOCATOR_STANDARD, "Push DisableLocation result to client");
231     };
232     size_t objectArgsNum = 0;
233     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
234 #endif
235 }
236 
RequestEnableLocation(napi_env env,napi_callback_info info)237 napi_value RequestEnableLocation(napi_env env, napi_callback_info info)
238 {
239     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
240     size_t argc = MAXIMUM_JS_PARAMS;
241     napi_value argv[MAXIMUM_JS_PARAMS];
242     napi_value thisVar = nullptr;
243     void* data = nullptr;
244     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
245     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
246 
247     auto asyncContext = new (std::nothrow) SwitchAsyncContext(env);
248     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
249     NAPI_CALL(env, napi_create_string_latin1(env, "enableLocation", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
250 
251     asyncContext->executeFunc = [&](void* data) -> void {
252         auto context = static_cast<SwitchAsyncContext*>(data);
253         if (!g_locatorClient->IsLocationEnabled()) {
254             g_locatorClient->ShowNotification();
255         }
256         g_locatorClient->EnableAbility(true);
257         context->errCode = SUCCESS;
258     };
259 
260     asyncContext->completeFunc = [&](void* data) -> void {
261         auto context = static_cast<SwitchAsyncContext*>(data);
262         NAPI_CALL_RETURN_VOID(context->env,
263             napi_get_boolean(context->env, context->errCode == SUCCESS, &context->result[PARAM1]));
264         LBSLOGI(LOCATOR_STANDARD, "Push RequestEnableLocation result to client");
265     };
266 
267     size_t objectArgsNum = 0;
268     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
269 }
270 
IsGeoServiceAvailable(napi_env env,napi_callback_info info)271 napi_value IsGeoServiceAvailable(napi_env env, napi_callback_info info)
272 {
273     size_t argc = MAXIMUM_JS_PARAMS;
274     napi_value argv[MAXIMUM_JS_PARAMS];
275     napi_value thisVar = nullptr;
276     void* data = nullptr;
277     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
278     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
279 #ifdef ENABLE_NAPI_MANAGER
280     napi_value res;
281     bool isAvailable = false;
282     LocationErrCode errorCode = g_locatorClient->IsGeoServiceAvailableV9(isAvailable);
283     if (errorCode != ERRCODE_SUCCESS) {
284         HandleSyncErrCode(env, errorCode);
285         return UndefinedNapiValue(env);
286     }
287     NAPI_CALL(env, napi_get_boolean(env, isAvailable, &res));
288     return res;
289 #else
290     auto asyncContext = new (std::nothrow) SwitchAsyncContext(env);
291     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
292     NAPI_CALL(env,
293         napi_create_string_latin1(env, "isGeoServiceAvailable", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
294     asyncContext->executeFunc = [&](void* data) -> void {
295         auto context = static_cast<SwitchAsyncContext*>(data);
296         bool isAvailable = g_locatorClient->IsGeoServiceAvailable();
297         context->enable = isAvailable;
298         context->errCode = SUCCESS;
299     };
300     asyncContext->completeFunc = [&](void* data) -> void {
301         auto context = static_cast<SwitchAsyncContext*>(data);
302         NAPI_CALL_RETURN_VOID(context->env, napi_get_boolean(context->env, context->enable, &context->result[PARAM1]));
303         LBSLOGI(LOCATOR_STANDARD, "Push isGeoServiceAvailable result to client");
304     };
305     size_t objectArgsNum = 0;
306     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
307 #endif
308 }
309 
CreateReverseGeocodeAsyncContext(ReverseGeoCodeAsyncContext * asyncContext)310 void CreateReverseGeocodeAsyncContext(ReverseGeoCodeAsyncContext* asyncContext)
311 {
312     asyncContext->executeFunc = [&](void* data) -> void {
313         auto context = static_cast<ReverseGeoCodeAsyncContext*>(data);
314 #ifdef ENABLE_NAPI_MANAGER
315         if (context->errCode != ERRCODE_SUCCESS) {
316 #else
317         if (context->errCode != SUCCESS) {
318 #endif
319             return;
320         }
321 #ifdef ENABLE_NAPI_MANAGER
322         bool isAvailable = false;
323         LocationErrCode errorCode = g_locatorClient->IsGeoServiceAvailableV9(isAvailable);
324         if (errorCode != ERRCODE_SUCCESS) {
325             context->errCode = errorCode;
326             return;
327         }
328         if (!isAvailable) {
329             context->errCode = ERRCODE_REVERSE_GEOCODING_FAIL;
330             return;
331         }
332         errorCode = g_locatorClient->GetAddressByCoordinateV9(context->reverseGeoCodeRequest, context->replyList);
333         if (context->replyList.empty() || errorCode != ERRCODE_SUCCESS) {
334             context->errCode = errorCode;
335         }
336 #else
337         if (!g_locatorClient->IsGeoServiceAvailable()) {
338             context->errCode = REVERSE_GEOCODE_ERROR;
339             return;
340         }
341         g_locatorClient->GetAddressByCoordinate(context->reverseGeoCodeRequest, context->replyList);
342         if (context->replyList.empty()) {
343             context->errCode = REVERSE_GEOCODE_ERROR;
344         }
345 #endif
346     };
347     asyncContext->completeFunc = [&](void* data) -> void {
348         auto context = static_cast<ReverseGeoCodeAsyncContext*>(data);
349         NAPI_CALL_RETURN_VOID(context->env,
350             napi_create_array_with_length(context->env, context->replyList.size(), &context->result[PARAM1]));
351         GeoAddressesToJsObj(context->env, context->replyList, context->result[PARAM1]);
352     };
353 }
354 
355 void CreateGeocodeAsyncContext(GeoCodeAsyncContext* asyncContext)
356 {
357     asyncContext->executeFunc = [&](void* data) -> void {
358         auto context = static_cast<GeoCodeAsyncContext*>(data);
359         if (context->errCode != SUCCESS) {
360             return;
361         }
362 #ifdef ENABLE_NAPI_MANAGER
363         bool isAvailable = false;
364         LocationErrCode errorCode = g_locatorClient->IsGeoServiceAvailableV9(isAvailable);
365         if (errorCode != ERRCODE_SUCCESS) {
366             context->errCode = errorCode;
367             return;
368         }
369         if (!isAvailable) {
370             context->errCode = ERRCODE_GEOCODING_FAIL;
371             return;
372         }
373         errorCode = g_locatorClient->GetAddressByLocationNameV9(context->geoCodeRequest, context->replyList);
374         if (context->replyList.empty() || errorCode != ERRCODE_SUCCESS) {
375             context->errCode = errorCode;
376         }
377 #else
378         if (!g_locatorClient->IsGeoServiceAvailable()) {
379             context->errCode = GEOCODE_ERROR;
380             return;
381         }
382         g_locatorClient->GetAddressByLocationName(context->geoCodeRequest, context->replyList);
383         if (context->replyList.empty()) {
384             context->errCode = GEOCODE_ERROR;
385         }
386 #endif
387     };
388     asyncContext->completeFunc = [&](void* data) -> void {
389         auto context = static_cast<GeoCodeAsyncContext*>(data);
390         NAPI_CALL_RETURN_VOID(context->env,
391             napi_create_array_with_length(context->env, context->replyList.size(), &context->result[PARAM1]));
392         GeoAddressesToJsObj(context->env, context->replyList, context->result[PARAM1]);
393         LBSLOGI(LOCATOR_STANDARD, "Push GetAddressesFromLocationName result to client");
394     };
395 }
396 
397 napi_value GetAddressesFromLocation(napi_env env, napi_callback_info info)
398 {
399     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
400     size_t argc = MAXIMUM_JS_PARAMS;
401     napi_value argv[MAXIMUM_JS_PARAMS];
402     napi_value thisVar = nullptr;
403     void* data = nullptr;
404     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
405     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
406 #ifdef ENABLE_NAPI_MANAGER
407     if (argc < PARAM1 || argc > PARAM2 || (argc == PARAM2 && !CheckIfParamIsFunctionType(env, argv[1]))) {
408         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
409         return UndefinedNapiValue(env);
410     }
411 #else
412     NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
413 #endif
414 
415     napi_valuetype valueType;
416     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
417 #ifdef ENABLE_NAPI_MANAGER
418     if (valueType != napi_object) {
419         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
420         return UndefinedNapiValue(env);
421     }
422 #else
423     NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type, object is expected for parameter 1.");
424 #endif
425     auto asyncContext = new (std::nothrow) ReverseGeoCodeAsyncContext(env);
426     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
427     NAPI_CALL(env, napi_create_string_latin1(env, "getAddressesFromLocation",
428         NAPI_AUTO_LENGTH, &asyncContext->resourceName));
429     bool ret = JsObjToReverseGeoCodeRequest(env, argv[0], asyncContext->reverseGeoCodeRequest);
430 #ifdef ENABLE_NAPI_MANAGER
431     asyncContext->errCode = ret ? ERRCODE_SUCCESS : ERRCODE_INVALID_PARAM;
432 #else
433     asyncContext->errCode = ret ? SUCCESS : INPUT_PARAMS_ERROR;
434 #endif
435 #ifdef ENABLE_NAPI_MANAGER
436     if (asyncContext->errCode != SUCCESS) {
437         int code = asyncContext->errCode;
438         delete asyncContext;
439         asyncContext = nullptr;
440         HandleSyncErrCode(env, code);
441         return UndefinedNapiValue(env);
442     }
443 #endif
444     CreateReverseGeocodeAsyncContext(asyncContext);
445 
446     size_t objectArgsNum = 1;
447     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
448 }
449 
450 napi_value GetAddressesFromLocationName(napi_env env, napi_callback_info info)
451 {
452     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
453     size_t argc = MAXIMUM_JS_PARAMS;
454     napi_value argv[MAXIMUM_JS_PARAMS];
455     napi_value thisVar = nullptr;
456     void* data = nullptr;
457     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
458     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
459 #ifdef ENABLE_NAPI_MANAGER
460     if (argc < PARAM1 || argc > PARAM2 || (argc == PARAM2 && !CheckIfParamIsFunctionType(env, argv[1]))) {
461         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
462         return UndefinedNapiValue(env);
463     }
464 #else
465     NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
466 #endif
467 
468     napi_valuetype valueType;
469     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
470 #ifdef ENABLE_NAPI_MANAGER
471     if (valueType != napi_object) {
472         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
473         return UndefinedNapiValue(env);
474     }
475 #else
476     NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type, object is expected for parameter 1.");
477 #endif
478     auto asyncContext = new (std::nothrow) GeoCodeAsyncContext(env);
479     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
480     NAPI_CALL(env,
481         napi_create_string_latin1(env, "GetAddressesFromLocationName", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
482     asyncContext->errCode = JsObjToGeoCodeRequest(env, argv[0], asyncContext->geoCodeRequest);
483 #ifdef ENABLE_NAPI_MANAGER
484     if (asyncContext->errCode == INPUT_PARAMS_ERROR) {
485         delete asyncContext;
486         asyncContext = nullptr;
487         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
488         return UndefinedNapiValue(env);
489     }
490 #endif
491     CreateGeocodeAsyncContext(asyncContext);
492     size_t objectArgsNum = 1;
493     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
494 }
495 
496 #ifdef ENABLE_NAPI_MANAGER
497 napi_value IsLocationPrivacyConfirmed(napi_env env, napi_callback_info info)
498 {
499     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
500     size_t argc = MAXIMUM_JS_PARAMS;
501     napi_value argv[MAXIMUM_JS_PARAMS];
502     napi_value thisVar = nullptr;
503     void* data = nullptr;
504     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
505     if (g_locatorClient == nullptr) {
506         HandleSyncErrCode(env, ERRCODE_SERVICE_UNAVAILABLE);
507         return UndefinedNapiValue(env);
508     }
509     // 1 arguement is necessary
510     if (argc != PARAM1) {
511         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
512         return UndefinedNapiValue(env);
513     }
514     napi_valuetype valueType;
515     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
516     if (valueType != napi_number) {
517         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
518         return UndefinedNapiValue(env);
519     }
520     int type;
521     NAPI_CALL(env, napi_get_value_int32(env, argv[0], &type));
522     napi_value res;
523     bool isEnabled = false;
524     LocationErrCode errorCode = g_locatorClient->IsLocationPrivacyConfirmedV9(type, isEnabled);
525     if (errorCode != ERRCODE_SUCCESS) {
526         HandleSyncErrCode(env, errorCode);
527         return UndefinedNapiValue(env);
528     }
529     NAPI_CALL(env, napi_get_boolean(env, isEnabled, &res));
530     return res;
531 }
532 
533 napi_value SetLocationPrivacyConfirmStatus(napi_env env, napi_callback_info info)
534 {
535     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
536     size_t argc = MAXIMUM_JS_PARAMS;
537     napi_value argv[MAXIMUM_JS_PARAMS];
538     napi_value thisVar = nullptr;
539     void* data = nullptr;
540     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
541     if (g_locatorClient == nullptr) {
542         HandleSyncErrCode(env, ERRCODE_SERVICE_UNAVAILABLE);
543         return UndefinedNapiValue(env);
544     }
545     // 2 arguement is necessary
546     if (argc != PARAM2) {
547         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
548         return UndefinedNapiValue(env);
549     }
550     napi_valuetype valueType1;
551     napi_valuetype valueType2;
552     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType1));
553     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType2));
554     if (valueType1 != napi_number || valueType2 != napi_boolean) {
555         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
556         return UndefinedNapiValue(env);
557     }
558     int type;
559     NAPI_CALL(env, napi_get_value_int32(env, argv[0], &type));
560     bool isConfirmed;
561     NAPI_CALL(env, napi_get_value_bool(env, argv[1], &isConfirmed));
562     LocationErrCode errorCode = g_locatorClient->SetLocationPrivacyConfirmStatusV9(type, isConfirmed);
563     if (errorCode != ERRCODE_SUCCESS) {
564         HandleSyncErrCode(env, errorCode);
565     }
566     return UndefinedNapiValue(env);
567 }
568 #endif
569 
570 napi_value GetCachedGnssLocationsSize(napi_env env, napi_callback_info info)
571 {
572     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
573     size_t argc = MAXIMUM_JS_PARAMS;
574     napi_value argv[MAXIMUM_JS_PARAMS];
575     napi_value thisVar = nullptr;
576     void* data = nullptr;
577     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
578     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
579 #ifdef ENABLE_NAPI_MANAGER
580     if (argc > PARAM1 || (argc == PARAM1 && !CheckIfParamIsFunctionType(env, argv[PARAM0]))) {
581         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
582         return UndefinedNapiValue(env);
583     }
584 #endif
585     auto asyncContext = new (std::nothrow) CachedAsyncContext(env);
586     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
587     NAPI_CALL(env,
588         napi_create_string_latin1(env, "GetCachedGnssLocationsSize", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
589 
590     asyncContext->executeFunc = [&](void* data) -> void {
591         auto context = static_cast<CachedAsyncContext*>(data);
592 #ifdef ENABLE_NAPI_MANAGER
593         LocationErrCode errorCode = CheckLocationSwitchState();
594         if (errorCode != ERRCODE_SUCCESS) {
595             context->errCode = errorCode;
596             return;
597         }
598 #endif
599 
600 #ifdef ENABLE_NAPI_MANAGER
601         int size = -1;
602         g_locatorClient->GetCachedGnssLocationsSizeV9(size);
603         context->errCode = ERRCODE_NOT_SUPPORTED;
604         context->locationSize = size;
605 #else
606         context->locationSize = g_locatorClient->GetCachedGnssLocationsSize();
607         context->errCode = (context->locationSize >= 0) ? SUCCESS : NOT_SUPPORTED;
608 #endif
609     };
610     asyncContext->completeFunc = [&](void* data) -> void {
611         auto context = static_cast<CachedAsyncContext*>(data);
612         NAPI_CALL_RETURN_VOID(context->env,
613             napi_create_int32(context->env, context->locationSize, &context->result[PARAM1]));
614         LBSLOGI(LOCATOR_STANDARD, "Push GetCachedGnssLocationsSize result to client");
615     };
616 
617     size_t objectArgsNum = 0;
618     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
619 }
620 
621 napi_value FlushCachedGnssLocations(napi_env env, napi_callback_info info)
622 {
623     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
624     size_t argc = MAXIMUM_JS_PARAMS;
625     napi_value argv[MAXIMUM_JS_PARAMS];
626     napi_value thisVar = nullptr;
627     void* data = nullptr;
628     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
629     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
630 #ifdef ENABLE_NAPI_MANAGER
631     if (argc > PARAM1 || (argc == PARAM1 && !CheckIfParamIsFunctionType(env, argv[PARAM0]))) {
632         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
633         return UndefinedNapiValue(env);
634     }
635 #endif
636     auto asyncContext = new (std::nothrow) CachedAsyncContext(env);
637     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
638     NAPI_CALL(env,
639         napi_create_string_latin1(env, "FlushCachedGnssLocations", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
640 
641     asyncContext->executeFunc = [&](void* data) -> void {
642         auto context = static_cast<CachedAsyncContext*>(data);
643 #ifdef ENABLE_NAPI_MANAGER
644         LocationErrCode errorCode = CheckLocationSwitchState();
645         if (errorCode != ERRCODE_SUCCESS) {
646             context->errCode = errorCode;
647             return;
648         }
649         g_locatorClient->FlushCachedGnssLocationsV9();
650         context->errCode = ERRCODE_NOT_SUPPORTED;
651 #else
652         if (g_locatorClient->IsLocationEnabled()) {
653             g_locatorClient->FlushCachedGnssLocations();
654         }
655         context->errCode = NOT_SUPPORTED;
656 #endif
657     };
658 
659     asyncContext->completeFunc = [&](void* data) -> void {
660         auto context = static_cast<CachedAsyncContext*>(data);
661 #ifdef ENABLE_NAPI_MANAGER
662         NAPI_CALL_RETURN_VOID(context->env, napi_get_undefined(context->env, &context->result[PARAM1]));
663 #else
664         NAPI_CALL_RETURN_VOID(context->env,
665             napi_get_boolean(context->env, context->errCode == SUCCESS, &context->result[PARAM1]));
666 #endif
667         LBSLOGI(LOCATOR_STANDARD, "Push FlushCachedGnssLocations result to client");
668     };
669 
670     size_t objectArgsNum = 0;
671     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
672 }
673 
674 void CreateCommandAsyncContext(CommandAsyncContext* asyncContext)
675 {
676     asyncContext->executeFunc = [&](void* data) -> void {
677         auto context = static_cast<CommandAsyncContext*>(data);
678 #ifdef ENABLE_NAPI_MANAGER
679         if (context->command != nullptr) {
680             context->errCode = g_locatorClient->SendCommandV9(context->command);
681         }
682 #else
683         if (context->command != nullptr) {
684             g_locatorClient->SendCommand(context->command);
685         }
686         context->errCode = NOT_SUPPORTED;
687 #endif
688     };
689     asyncContext->completeFunc = [&](void* data) -> void {
690         auto context = static_cast<CommandAsyncContext*>(data);
691 #ifdef ENABLE_NAPI_MANAGER
692         NAPI_CALL_RETURN_VOID(context->env, napi_get_undefined(context->env, &context->result[PARAM1]));
693 #else
694         NAPI_CALL_RETURN_VOID(context->env, napi_get_boolean(context->env,
695             context->enable, &context->result[PARAM1]));
696 #endif
697         LBSLOGI(LOCATOR_STANDARD, "Push SendCommand result to client");
698     };
699 }
700 
701 napi_value SendCommand(napi_env env, napi_callback_info info)
702 {
703     size_t argc = MAXIMUM_JS_PARAMS;
704     napi_value argv[MAXIMUM_JS_PARAMS];
705     napi_value thisVar = nullptr;
706     void* data = nullptr;
707     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
708     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
709 #ifdef ENABLE_NAPI_MANAGER
710     if (argc < PARAM1 || argc > PARAM2 || (argc == PARAM2 && !CheckIfParamIsFunctionType(env, argv[1]))) {
711         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
712         return UndefinedNapiValue(env);
713     }
714 #else
715     NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
716 #endif
717 
718     napi_valuetype valueType;
719     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
720 #ifdef ENABLE_NAPI_MANAGER
721     if (valueType != napi_object) {
722         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
723         return UndefinedNapiValue(env);
724     }
725 #else
726     NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type, object is expected for parameter 1.");
727 #endif
728 
729 #ifdef ENABLE_NAPI_MANAGER
730     if (argc == PARAM2 && !CheckIfParamIsFunctionType(env, argv[PARAM1])) {
731         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
732         return UndefinedNapiValue(env);
733     }
734 #endif
735     auto asyncContext = new (std::nothrow) CommandAsyncContext(env);
736     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
737     asyncContext->command = std::make_unique<LocationCommand>();
738     NAPI_CALL(env, napi_create_string_latin1(env, "SendCommand", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
739 
740     int errCode = JsObjToCommand(env, argv[0], asyncContext->command);
741 #ifdef ENABLE_NAPI_MANAGER
742     if (errCode == INPUT_PARAMS_ERROR) {
743         delete asyncContext;
744         asyncContext = nullptr;
745         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
746         return UndefinedNapiValue(env);
747     }
748 #else
749     NAPI_ASSERT(env, errCode != INPUT_PARAMS_ERROR, "The input params should be checked first.");
750 #endif
751     CreateCommandAsyncContext(asyncContext);
752     size_t objectArgsNum = 1;
753     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
754 }
755 
756 #ifdef ENABLE_NAPI_MANAGER
757 napi_value GetIsoCountryCode(napi_env env, napi_callback_info info)
758 {
759     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
760     size_t argc = MAXIMUM_JS_PARAMS;
761     napi_value argv[MAXIMUM_JS_PARAMS];
762     napi_value thisVar = nullptr;
763     void *data = nullptr;
764     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
765     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
766     if (argc > PARAM1 || (argc == PARAM1 && !CheckIfParamIsFunctionType(env, argv[PARAM0]))) {
767         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
768         return UndefinedNapiValue(env);
769     }
770     CountryCodeContext *asyncContext = new (std::nothrow) CountryCodeContext(env);
771     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
772     if (napi_create_string_latin1(env, "CountryCodeContext", NAPI_AUTO_LENGTH,
773         &asyncContext->resourceName) != napi_ok) {
774         LBSLOGE(LOCATOR_STANDARD, "copy string failed");
775     }
776     asyncContext->executeFunc = [&](void *data) -> void {
777         if (data == nullptr) {
778             LBSLOGE(LOCATOR_STANDARD, "GetIsoCountryCode data == nullptr");
779             return;
780         }
781         CountryCodeContext *context = static_cast<CountryCodeContext*>(data);
782         std::shared_ptr<CountryCode> country = std::make_shared<CountryCode>();
783         LocationErrCode errorCode = g_locatorClient->GetIsoCountryCodeV9(country);
784         context->errCode = errorCode;
785         if (errorCode == ERRCODE_SUCCESS) {
786             context->country = country;
787         }
788     };
789     asyncContext->completeFunc = [&](void *data) -> void {
790         if (data == nullptr) {
791             LBSLOGE(LOCATOR_STANDARD, "GetIsoCountryCode data == nullptr");
792             return;
793         }
794         CountryCodeContext *context = static_cast<CountryCodeContext *>(data);
795         NAPI_CALL_RETURN_VOID(context->env, napi_create_object(context->env, &context->result[PARAM1]));
796         if (context->country) {
797             CountryCodeToJs(context->env, context->country, context->result[PARAM1]);
798         } else {
799             LBSLOGE(LOCATOR_STANDARD, "country is nullptr!");
800         }
801         LBSLOGI(LOCATOR_STANDARD, "Push GetIsoCountryCode result to client");
802     };
803 
804     size_t objectArgsNum = 0;
805     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
806 }
807 
808 int ParseLocationMockParams(napi_env env, LocationMockAsyncContext *asyncContext, napi_value object)
809 {
810     CHK_ERROR_CODE("timeInterval", JsObjectToInt(env, object, "timeInterval", asyncContext->timeInterval), true);
811     bool result = false;
812     napi_value value = nullptr;
813     NAPI_CALL_BASE(env, napi_has_named_property(env, object, "locations", &result), false);
814     if (result) {
815         NAPI_CALL_BASE(env, napi_get_named_property(env, object, "locations", &value), false);
816         bool isArray = false;
817         NAPI_CALL_BASE(env, napi_is_array(env, value, &isArray), false);
818         if (!isArray) {
819             LBSLOGE(LOCATOR_STANDARD, "not an array!");
820             return INPUT_PARAMS_ERROR;
821         }
822         GetLocationArray(env, asyncContext, value);
823     }
824     return SUCCESS;
825 }
826 
827 napi_value EnableLocationMock(napi_env env, napi_callback_info info)
828 {
829     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
830     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
831     LocationErrCode errorCode = CheckLocationSwitchState();
832     if (errorCode != ERRCODE_SUCCESS) {
833         HandleSyncErrCode(env, errorCode);
834         return UndefinedNapiValue(env);
835     }
836     errorCode = g_locatorClient->EnableLocationMockV9();
837     if (errorCode != ERRCODE_SUCCESS) {
838         HandleSyncErrCode(env, errorCode);
839     }
840     return UndefinedNapiValue(env);
841 }
842 
843 napi_value DisableLocationMock(napi_env env, napi_callback_info info)
844 {
845     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
846     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
847     LocationErrCode errorCode = CheckLocationSwitchState();
848     if (errorCode != ERRCODE_SUCCESS) {
849         HandleSyncErrCode(env, errorCode);
850         return UndefinedNapiValue(env);
851     }
852     errorCode = g_locatorClient->DisableLocationMockV9();
853     if (errorCode != ERRCODE_SUCCESS) {
854         HandleSyncErrCode(env, errorCode);
855     }
856     return UndefinedNapiValue(env);
857 }
858 
859 napi_value SetMockedLocations(napi_env env, napi_callback_info info)
860 {
861     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
862     size_t argc = MAXIMUM_JS_PARAMS;
863     napi_value argv[MAXIMUM_JS_PARAMS];
864     napi_value thisVar = nullptr;
865     void *data = nullptr;
866     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
867     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
868     if (argc != PARAM1) {
869         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
870         return UndefinedNapiValue(env);
871     }
872     napi_valuetype valueType;
873     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
874     if (valueType != napi_object) {
875         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
876         return UndefinedNapiValue(env);
877     }
878 
879     LocationMockAsyncContext *asyncContext = new (std::nothrow) LocationMockAsyncContext(env);
880     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
881     NAPI_CALL(env, napi_create_string_latin1(env,
882         "SetMockedLocations", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
883     asyncContext->errCode = ParseLocationMockParams(env, asyncContext, argv[0]);
884     if (asyncContext->errCode == INPUT_PARAMS_ERROR) {
885         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
886         return UndefinedNapiValue(env);
887     }
888     LocationErrCode errorCode = CheckLocationSwitchState();
889     if (errorCode != ERRCODE_SUCCESS) {
890         HandleSyncErrCode(env, errorCode);
891         return UndefinedNapiValue(env);
892     }
893     errorCode = g_locatorClient->SetMockedLocationsV9(asyncContext->timeInterval, asyncContext->LocationNapi);
894     if (errorCode != ERRCODE_SUCCESS) {
895         HandleSyncErrCode(env, errorCode);
896     }
897     return UndefinedNapiValue(env);
898 }
899 
900 napi_value EnableReverseGeocodingMock(napi_env env, napi_callback_info info)
901 {
902     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
903     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
904     LocationErrCode errorCode = g_locatorClient->EnableReverseGeocodingMockV9();
905     if (errorCode != ERRCODE_SUCCESS) {
906         HandleSyncErrCode(env, errorCode);
907     }
908     return UndefinedNapiValue(env);
909 }
910 
911 napi_value DisableReverseGeocodingMock(napi_env env, napi_callback_info info)
912 {
913     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
914     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
915     LocationErrCode errorCode = g_locatorClient->DisableReverseGeocodingMockV9();
916     if (errorCode != ERRCODE_SUCCESS) {
917         HandleSyncErrCode(env, errorCode);
918     }
919     return UndefinedNapiValue(env);
920 }
921 
922 napi_value SetReverseGeocodingMockInfo(napi_env env, napi_callback_info info)
923 {
924     LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
925     size_t argc = MAXIMUM_JS_PARAMS;
926     napi_value argv[MAXIMUM_JS_PARAMS];
927     napi_value thisVar = nullptr;
928     void *data = nullptr;
929     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
930     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
931     if (argc != PARAM1) {
932         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
933         return UndefinedNapiValue(env);
934     }
935 
936     bool isArray = false;
937     NAPI_CALL(env, napi_is_array(env, argv[0], &isArray));
938     if (!isArray) {
939         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
940         return UndefinedNapiValue(env);
941     }
942     std::vector<std::shared_ptr<GeocodingMockInfo>> mockInfo;
943     JsObjToRevGeocodeMock(env, argv[0], mockInfo);
944     LocationErrCode errorCode = g_locatorClient->SetReverseGeocodingMockInfoV9(mockInfo);
945     if (errorCode != ERRCODE_SUCCESS) {
946         HandleSyncErrCode(env, errorCode);
947     }
948     return UndefinedNapiValue(env);
949 }
950 #endif
951 
952 #ifdef ENABLE_NAPI_MANAGER
953 LocationErrCode CheckLocationSwitchState()
954 {
955     bool isEnabled = false;
956     LocationErrCode errorCode = g_locatorClient->IsLocationEnabledV9(isEnabled);
957     if (errorCode != ERRCODE_SUCCESS) {
958         return errorCode;
959     }
960     if (!isEnabled) {
961         return ERRCODE_SWITCH_OFF;
962     }
963     return ERRCODE_SUCCESS;
964 }
965 
966 sptr<LocatingRequiredDataCallbackNapi> CreateSingleCallbackHost()
967 {
968     auto callbackHost =
969         sptr<LocatingRequiredDataCallbackNapi>(new (std::nothrow) LocatingRequiredDataCallbackNapi());
970     if (callbackHost) {
971         callbackHost->SetFixNumber(1);
972     }
973     return callbackHost;
974 }
975 
976 SingleScanAsyncContext* CreateSingleScanAsyncContext(const napi_env& env,
977     std::unique_ptr<LocatingRequiredDataConfig>& config, sptr<LocatingRequiredDataCallbackNapi> callback)
978 {
979     auto asyncContext = new (std::nothrow) SingleScanAsyncContext(env);
980     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
981     NAPI_CALL(env, napi_create_string_latin1(env, "getLocatingRequiredDataOnce",
982         NAPI_AUTO_LENGTH, &asyncContext->resourceName));
983     asyncContext->timeout_ = config->GetScanTimeoutMs();
984     asyncContext->callbackHost_ = callback;
985     asyncContext->executeFunc = [&](void* data) -> void {
986         if (data == nullptr) {
987             LBSLOGE(LOCATOR_STANDARD, "data is nullptr!");
988             return;
989         }
990         auto context = static_cast<SingleScanAsyncContext*>(data);
991         auto callbackHost = context->callbackHost_;
992         if (callbackHost != nullptr) {
993             callbackHost->Wait(context->timeout_);
994             auto callbackPtr = sptr<ILocatingRequiredDataCallback>(callbackHost);
995             g_locatorClient->UnRegisterLocatingRequiredDataCallback(callbackPtr);
996             if (callbackHost->GetCount() != 0) {
997                 context->errCode = ERRCODE_SCAN_FAIL;
998             }
999             callbackHost->SetCount(1);
1000         }
1001     };
1002     asyncContext->completeFunc = [&](void* data) -> void {
1003         if (data == nullptr) {
1004             LBSLOGE(LOCATOR_STANDARD, "data is nullptr!");
1005             return;
1006         }
1007         auto context = static_cast<SingleScanAsyncContext*>(data);
1008 
1009         auto callbackHost = context->callbackHost_;
1010         if (callbackHost != nullptr) {
1011             std::vector<std::shared_ptr<LocatingRequiredData>> res = callbackHost->GetSingleResult();
1012             napi_create_array_with_length(context->env, res.size(), &context->result[PARAM1]);
1013             LocatingRequiredDataToJsObj(context->env, res, context->result[PARAM1]);
1014             callbackHost->ClearSingleResult();
1015         } else {
1016             LBSLOGE(LOCATOR_STANDARD, "m_singleLocation is nullptr!");
1017         }
1018         if (context->callbackHost_) {
1019             context->callbackHost_ = nullptr;
1020         }
1021         LBSLOGI(LOCATOR_STANDARD, "Push scan info to client");
1022     };
1023     return asyncContext;
1024 }
1025 
1026 napi_value GetLocatingRequiredData(napi_env env, napi_callback_info info)
1027 {
1028     LBSLOGD(LOCATOR_STANDARD, "%{public}s called.", __func__);
1029     size_t argc = MAXIMUM_JS_PARAMS;
1030     napi_value argv[MAXIMUM_JS_PARAMS];
1031     napi_value thisVar = nullptr;
1032     void* data = nullptr;
1033     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
1034     NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
1035     if (argc > PARAM1 || (argc == PARAM1 && !CheckIfParamIsObjectType(env, argv[PARAM0]))) {
1036         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1037         return UndefinedNapiValue(env);
1038     }
1039     if (argc == PARAM1) {
1040         napi_valuetype valueType;
1041         NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
1042         if (valueType != napi_object) {
1043             HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1044             return UndefinedNapiValue(env);
1045         }
1046     }
1047 
1048     auto singleCallbackHost = CreateSingleCallbackHost();
1049     if (singleCallbackHost == nullptr) {
1050         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1051         return UndefinedNapiValue(env);
1052     }
1053     std::unique_ptr<LocatingRequiredDataConfig> requestConfig = std::make_unique<LocatingRequiredDataConfig>();
1054     JsObjToLocatingRequiredDataConfig(env, argv[0], requestConfig);
1055     requestConfig->SetFixNumber(1);
1056     auto callbackPtr = sptr<ILocatingRequiredDataCallback>(singleCallbackHost);
1057     LocationErrCode errorCode = g_locatorClient->RegisterLocatingRequiredDataCallback(requestConfig, callbackPtr);
1058     if (errorCode != ERRCODE_SUCCESS) {
1059         HandleSyncErrCode(env, errorCode);
1060         return UndefinedNapiValue(env);
1061     }
1062 
1063     auto asyncContext = CreateSingleScanAsyncContext(env, requestConfig, singleCallbackHost);
1064     if (asyncContext == nullptr) {
1065         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1066         return UndefinedNapiValue(env);
1067     }
1068     return DoAsyncWork(env, asyncContext, argc, argv, 1);
1069 }
1070 
1071 napi_value AddGnssGeofence(napi_env env, napi_callback_info info)
1072 {
1073     LBSLOGD(LOCATOR_STANDARD, "%{public}s called.", __func__);
1074     size_t argc = MAXIMUM_JS_PARAMS;
1075     napi_value argv[MAXIMUM_JS_PARAMS];
1076     napi_value thisVar = nullptr;
1077     void* data = nullptr;
1078     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
1079     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator ext SA failed");
1080     if (argc > PARAM1) {
1081         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1082         return UndefinedNapiValue(env);
1083     }
1084     std::shared_ptr<GeofenceRequest> gnssGeofenceRequest = std::make_shared<GeofenceRequest>();
1085     bool isValidParameter = ParseGnssGeofenceRequest(env, argv[0], gnssGeofenceRequest);
1086     if (!isValidParameter) {
1087         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1088         return UndefinedNapiValue(env);
1089     }
1090     auto locationGnssGeofenceCallbackHost =
1091         sptr<LocationGnssGeofenceCallbackNapi>(new (std::nothrow) LocationGnssGeofenceCallbackNapi());
1092     JsObjToGeofenceTransitionCallback(env, argv[0], locationGnssGeofenceCallbackHost);
1093     auto callbackPtr = sptr<IGnssGeofenceCallback>(locationGnssGeofenceCallbackHost);
1094     gnssGeofenceRequest->SetGeofenceTransitionCallback(callbackPtr->AsObject());
1095     auto asyncContext = CreateAsyncContextForAddGnssGeofence(
1096         env, gnssGeofenceRequest, locationGnssGeofenceCallbackHost);
1097     if (asyncContext == nullptr) {
1098         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1099         return UndefinedNapiValue(env);
1100     }
1101     return DoAsyncWork(env, asyncContext, argc, argv, 1);
1102 }
1103 
1104 GnssGeofenceAsyncContext* CreateAsyncContextForAddGnssGeofence(const napi_env& env,
1105     std::shared_ptr<GeofenceRequest>& request, sptr<LocationGnssGeofenceCallbackNapi> callback)
1106 {
1107     auto asyncContext = new (std::nothrow) GnssGeofenceAsyncContext(env);
1108     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
1109     NAPI_CALL(env, napi_create_string_latin1(env, "addGnssGeofence", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
1110     asyncContext->callbackHost_ = callback;
1111     asyncContext->request_ = request;
1112     asyncContext->executeFunc = [&](void* data) -> void {
1113         if (data == nullptr) {
1114             return;
1115         }
1116         auto context = static_cast<GnssGeofenceAsyncContext*>(data);
1117         auto callbackHost = context->callbackHost_;
1118         auto gnssGeofenceRequest = context->request_;
1119         if (callbackHost != nullptr && gnssGeofenceRequest != nullptr) {
1120             auto errCode = g_geofenceClient->AddGnssGeofence(gnssGeofenceRequest);
1121             if (errCode != ERRCODE_SUCCESS) {
1122                 context->errCode = errCode;
1123                 callbackHost->SetCount(0);
1124             }
1125             callbackHost->Wait(DEFAULT_CALLBACK_WAIT_TIME);
1126             if (callbackHost->GetCount() != 0) {
1127                 context->errCode = ERRCODE_SERVICE_UNAVAILABLE;
1128             }
1129             callbackHost->SetCount(1);
1130         }
1131     };
1132     asyncContext->completeFunc = [&](void* data) -> void {
1133         if (data == nullptr) {
1134             return;
1135         }
1136         auto context = static_cast<GnssGeofenceAsyncContext*>(data);
1137         auto callbackHost = context->callbackHost_;
1138         if (callbackHost != nullptr && context->errCode == ERRCODE_SUCCESS &&
1139             callbackHost->GetGeofenceOperationType() == GnssGeofenceOperateType::GNSS_GEOFENCE_OPT_TYPE_ADD) {
1140             LocationErrCode errCode = callbackHost->DealGeofenceOperationResult();
1141             if (errCode == ERRCODE_SUCCESS) {
1142                 int fenceId = callbackHost->GetFenceId();
1143                 napi_create_object(context->env, &context->result[PARAM1]);
1144                 napi_create_int64(context->env, fenceId, &context->result[PARAM1]);
1145                 AddCallbackToGnssGeofenceCallbackHostMap(fenceId, callbackHost);
1146             } else {
1147                 context->errCode = errCode;
1148             }
1149         }
1150     };
1151     return asyncContext;
1152 }
1153 
1154 napi_value RemoveGnssGeofence(napi_env env, napi_callback_info info)
1155 {
1156     LBSLOGD(LOCATOR_STANDARD, "%{public}s called.", __func__);
1157     size_t argc = MAXIMUM_JS_PARAMS;
1158     napi_value argv[MAXIMUM_JS_PARAMS];
1159     napi_value thisVar = nullptr;
1160     void* data = nullptr;
1161     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
1162     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
1163     if (argc > PARAM1) {
1164         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1165         return UndefinedNapiValue(env);
1166     }
1167     int fenceId = -1;
1168     napi_valuetype valueType1;
1169     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType1));
1170     if (valueType1 != napi_number) {
1171         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1172         return UndefinedNapiValue(env);
1173     }
1174     NAPI_CALL(env, napi_get_value_int32(env, argv[0], &fenceId));
1175     auto asyncContext = CreateAsyncContextForRemoveGnssGeofence(env, fenceId);
1176     if (asyncContext == nullptr) {
1177         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1178         return UndefinedNapiValue(env);
1179     }
1180     size_t objectArgsNum = 1;
1181     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
1182 }
1183 
1184 GnssGeofenceAsyncContext* CreateAsyncContextForRemoveGnssGeofence(const napi_env& env, int fenceId)
1185 {
1186     auto asyncContext = new (std::nothrow) GnssGeofenceAsyncContext(env);
1187     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
1188     asyncContext->fenceId_ = fenceId;
1189     asyncContext->callbackHost_ = FindCallbackInGnssGeofenceCallbackHostMap(fenceId);
1190     NAPI_CALL(env, napi_create_string_latin1(env,
1191         "removeGnssGeofence", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
1192 
1193     asyncContext->executeFunc = [&](void* data) -> void {
1194         auto context = static_cast<GnssGeofenceAsyncContext*>(data);
1195         std::shared_ptr<GeofenceRequest> request = std::make_shared<GeofenceRequest>();
1196         request->SetFenceId(context->fenceId_);
1197         context->errCode = g_geofenceClient->RemoveGnssGeofence(request);
1198         auto callbackHost = context->callbackHost_;
1199         if (callbackHost != nullptr) {
1200             if (context->errCode != ERRCODE_SUCCESS) {
1201                 callbackHost->SetCount(0);
1202             }
1203             callbackHost->Wait(DEFAULT_CALLBACK_WAIT_TIME);
1204             if (callbackHost->GetCount() != 0) {
1205                 context->errCode = ERRCODE_SERVICE_UNAVAILABLE;
1206             }
1207             callbackHost->SetCount(1);
1208         } else {
1209             context->errCode = ERRCODE_GEOFENCE_INCORRECT_ID;
1210         }
1211     };
1212 
1213     asyncContext->completeFunc = [&](void* data) -> void {
1214         auto context = static_cast<GnssGeofenceAsyncContext*>(data);
1215         auto callbackHost = context->callbackHost_;
1216         if (callbackHost != nullptr && context->errCode == ERRCODE_SUCCESS &&
1217             callbackHost->GetGeofenceOperationType() ==
1218             GnssGeofenceOperateType::GNSS_GEOFENCE_OPT_TYPE_DELETE) {
1219             LocationErrCode errCode = callbackHost->DealGeofenceOperationResult();
1220             if (errCode == ERRCODE_SUCCESS) {
1221                 NAPI_CALL_RETURN_VOID(
1222                     context->env, napi_get_undefined(context->env, &context->result[PARAM1]));
1223                 RemoveCallbackToGnssGeofenceCallbackHostMap(context->fenceId_);
1224             } else {
1225                 context->errCode = errCode;
1226             }
1227         }
1228         LBSLOGD(LOCATOR_STANDARD, "Push RemoveGnssGeofence result to client");
1229     };
1230     return asyncContext;
1231 }
1232 
1233 napi_value GetGeofenceSupportedCoordTypes(napi_env env, napi_callback_info info)
1234 {
1235     size_t argc = MAXIMUM_JS_PARAMS;
1236     napi_value argv[MAXIMUM_JS_PARAMS];
1237     napi_value thisVar = nullptr;
1238     void* data = nullptr;
1239     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
1240     NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
1241     std::vector<CoordinateSystemType> coordinateSystemTypes;
1242     LocationErrCode errorCode =
1243         g_geofenceClient->GetGeofenceSupportedCoordTypes(coordinateSystemTypes);
1244     if (errorCode != ERRCODE_SUCCESS) {
1245         HandleSyncErrCode(env, errorCode);
1246         return UndefinedNapiValue(env);
1247     }
1248     napi_value res;
1249     NAPI_CALL(env,
1250         napi_create_array_with_length(env, coordinateSystemTypes.size(), &res));
1251     uint32_t idx = 0;
1252     for (auto iter = coordinateSystemTypes.begin(); iter != coordinateSystemTypes.end(); ++iter) {
1253         auto coordType = *iter;
1254         napi_value eachObj;
1255         NAPI_CALL(env, napi_create_int32(env, static_cast<int>(coordType), &eachObj));
1256         NAPI_CALL(env, napi_set_element(env, res, idx++, eachObj));
1257     }
1258     return res;
1259 }
1260 
1261 void AddCallbackToGnssGeofenceCallbackHostMap(int fenceId, sptr<LocationGnssGeofenceCallbackNapi> callbackHost)
1262 {
1263     std::unique_lock<std::mutex> lock(g_gnssGeofenceCallbackHostMutex);
1264     g_gnssGeofenceCallbackHostMap.insert(std::make_pair(fenceId, callbackHost));
1265 }
1266 
1267 void RemoveCallbackToGnssGeofenceCallbackHostMap(int fenceId)
1268 {
1269     std::unique_lock<std::mutex> lock(g_gnssGeofenceCallbackHostMutex);
1270     auto iterForDelete = g_gnssGeofenceCallbackHostMap.find(fenceId);
1271     if (iterForDelete != g_gnssGeofenceCallbackHostMap.end()) {
1272         g_gnssGeofenceCallbackHostMap.erase(iterForDelete);
1273     }
1274 }
1275 
1276 sptr<LocationGnssGeofenceCallbackNapi> FindCallbackInGnssGeofenceCallbackHostMap(int fenceId)
1277 {
1278     std::unique_lock<std::mutex> lock(g_gnssGeofenceCallbackHostMutex);
1279     auto iter = g_gnssGeofenceCallbackHostMap.find(fenceId);
1280     if (iter != g_gnssGeofenceCallbackHostMap.end()) {
1281         return iter->second;
1282     }
1283     return nullptr;
1284 }
1285 #endif
1286 } // namespace Location
1287 } // namespace OHOS
1288