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 #include "location_napi_event.h"
16 
17 #include "callback_manager.h"
18 #include "common_utils.h"
19 #include "location_log.h"
20 #include "location_napi_errcode.h"
21 #include "country_code_callback_napi.h"
22 #include "locator.h"
23 #include "geofence_sdk.h"
24 #include "geofence_napi.h"
25 #include "napi_util.h"
26 #ifdef SUPPORT_JSSTACK
27 #include "xpower_event_js.h"
28 #endif
29 #include "want_agent_helper.h"
30 
31 namespace OHOS {
32 namespace Location {
33 CallbackManager<LocationSwitchCallbackNapi> g_switchCallbacks;
34 CallbackManager<LocatorCallbackNapi> g_locationCallbacks;
35 CallbackManager<GnssStatusCallbackNapi> g_gnssStatusInfoCallbacks;
36 CallbackManager<NmeaMessageCallbackNapi> g_nmeaCallbacks;
37 CallbackManager<CachedLocationsCallbackNapi> g_cachedLocationCallbacks;
38 CallbackManager<CountryCodeCallbackNapi> g_countryCodeCallbacks;
39 CallbackManager<LocatingRequiredDataCallbackNapi> g_locatingRequiredDataCallbacks;
40 CallbackManager<LocationErrorCallbackNapi> g_locationErrorCallbackHosts;
41 
42 std::unique_ptr<CachedGnssLocationsRequest> g_cachedRequest = std::make_unique<CachedGnssLocationsRequest>();
43 auto g_locatorProxy = Locator::GetInstance();
44 auto g_geofenceProxy = GeofenceManager::GetInstance();
45 
46 std::mutex g_FuncMapMutex;
47 std::map<std::string, bool(*)(const napi_env &)> g_offAllFuncMap;
48 std::map<std::string, bool(*)(const napi_env &, const napi_value &)> g_offFuncMap;
49 std::map<std::string, bool(*)(const napi_env &, const size_t, const napi_value *)> g_onFuncMap;
50 
51 static constexpr int LASTLOCATION_CACHED_TIME = 10 * 60;
52 
53 const int MIN_TIMEOUTMS_FOR_LOCATIONONCE = 1000;
54 
InitOnFuncMap()55 void InitOnFuncMap()
56 {
57     std::unique_lock<std::mutex> lock(g_FuncMapMutex);
58     if (g_onFuncMap.size() != 0) {
59         return;
60     }
61 #ifdef ENABLE_NAPI_MANAGER
62     g_onFuncMap.insert(std::make_pair("locationEnabledChange", &OnLocationServiceStateCallback));
63     g_onFuncMap.insert(std::make_pair("cachedGnssLocationsChange", &OnCachedGnssLocationsReportingCallback));
64     g_onFuncMap.insert(std::make_pair("satelliteStatusChange", &OnGnssStatusChangeCallback));
65     g_onFuncMap.insert(std::make_pair("gnssFenceStatusChange", &OnFenceStatusChangeCallback));
66     g_onFuncMap.insert(std::make_pair("nmeaMessage", &OnNmeaMessageChangeCallback));
67     g_onFuncMap.insert(std::make_pair("locatingRequiredDataChange", &OnLocatingRequiredDataChangeCallback));
68     g_onFuncMap.insert(std::make_pair("locationError", &OnLocationErrorCallback));
69 #else
70     g_onFuncMap.insert(std::make_pair("locationServiceState", &OnLocationServiceStateCallback));
71     g_onFuncMap.insert(std::make_pair("cachedGnssLocationsReporting", &OnCachedGnssLocationsReportingCallback));
72     g_onFuncMap.insert(std::make_pair("gnssStatusChange", &OnGnssStatusChangeCallback));
73     g_onFuncMap.insert(std::make_pair("fenceStatusChange", &OnFenceStatusChangeCallback));
74     g_onFuncMap.insert(std::make_pair("nmeaMessageChange", &OnNmeaMessageChangeCallback));
75 #endif
76     g_onFuncMap.insert(std::make_pair("locationChange", &OnLocationChangeCallback));
77     g_onFuncMap.insert(std::make_pair("countryCodeChange", &OnCountryCodeChangeCallback));
78 }
79 
InitOffFuncMap()80 void InitOffFuncMap()
81 {
82     std::unique_lock<std::mutex> lock(g_FuncMapMutex);
83     if (g_offAllFuncMap.size() != 0 || g_offFuncMap.size() != 0) {
84         return;
85     }
86 #ifdef ENABLE_NAPI_MANAGER
87     g_offAllFuncMap.insert(std::make_pair("locationEnabledChange", &OffAllLocationServiceStateCallback));
88     g_offAllFuncMap.insert(std::make_pair("cachedGnssLocationsChange", &OffAllCachedGnssLocationsReportingCallback));
89     g_offAllFuncMap.insert(std::make_pair("satelliteStatusChange", &OffAllGnssStatusChangeCallback));
90     g_offAllFuncMap.insert(std::make_pair("nmeaMessage", &OffAllNmeaMessageChangeCallback));
91     g_offAllFuncMap.insert(std::make_pair("locatingRequiredDataChange", &OffAllLocatingRequiredDataChangeCallback));
92 #else
93     g_offAllFuncMap.insert(std::make_pair("locationServiceState", &OffAllLocationServiceStateCallback));
94     g_offAllFuncMap.insert(std::make_pair("cachedGnssLocationsReporting", &OffAllCachedGnssLocationsReportingCallback));
95     g_offAllFuncMap.insert(std::make_pair("gnssStatusChange", &OffAllGnssStatusChangeCallback));
96     g_offAllFuncMap.insert(std::make_pair("nmeaMessageChange", &OffAllNmeaMessageChangeCallback));
97 #endif
98     g_offAllFuncMap.insert(std::make_pair("locationChange", &OffAllLocationChangeCallback));
99     g_offAllFuncMap.insert(std::make_pair("countryCodeChange", &OffAllCountryCodeChangeCallback));
100 
101 #ifdef ENABLE_NAPI_MANAGER
102     g_offFuncMap.insert(std::make_pair("locationEnabledChange", &OffLocationServiceStateCallback));
103     g_offFuncMap.insert(std::make_pair("cachedGnssLocationsChange", &OffCachedGnssLocationsReportingCallback));
104     g_offFuncMap.insert(std::make_pair("satelliteStatusChange", &OffGnssStatusChangeCallback));
105     g_offFuncMap.insert(std::make_pair("nmeaMessage", &OffNmeaMessageChangeCallback));
106     g_offFuncMap.insert(std::make_pair("locatingRequiredDataChange", &OffLocatingRequiredDataChangeCallback));
107     g_offFuncMap.insert(std::make_pair("locationError", &OffLocationErrorCallback));
108 #else
109     g_offFuncMap.insert(std::make_pair("locationServiceState", &OffLocationServiceStateCallback));
110     g_offFuncMap.insert(std::make_pair("cachedGnssLocationsReporting", &OffCachedGnssLocationsReportingCallback));
111     g_offFuncMap.insert(std::make_pair("gnssStatusChange", &OffGnssStatusChangeCallback));
112     g_offFuncMap.insert(std::make_pair("nmeaMessageChange", &OffNmeaMessageChangeCallback));
113 #endif
114     g_offFuncMap.insert(std::make_pair("locationChange", &OffLocationChangeCallback));
115     g_offFuncMap.insert(std::make_pair("countryCodeChange", &OffCountryCodeChangeCallback));
116 }
117 
SubscribeLocationServiceState(const napi_env & env,const napi_ref & handlerRef,sptr<LocationSwitchCallbackNapi> & switchCallbackHost)118 void SubscribeLocationServiceState(const napi_env& env,
119     const napi_ref& handlerRef, sptr<LocationSwitchCallbackNapi>& switchCallbackHost)
120 {
121     switchCallbackHost->SetEnv(env);
122     switchCallbackHost->SetHandleCb(handlerRef);
123     g_locatorProxy->RegisterSwitchCallback(switchCallbackHost->AsObject(), DEFAULT_UID);
124 }
125 
126 #ifdef ENABLE_NAPI_MANAGER
SubscribeLocationServiceStateV9(const napi_env & env,const napi_ref & handlerRef,sptr<LocationSwitchCallbackNapi> & switchCallbackHost)127 LocationErrCode SubscribeLocationServiceStateV9(const napi_env& env,
128     const napi_ref& handlerRef, sptr<LocationSwitchCallbackNapi>& switchCallbackHost)
129 {
130     switchCallbackHost->SetEnv(env);
131     switchCallbackHost->SetHandleCb(handlerRef);
132     return g_locatorProxy->RegisterSwitchCallbackV9(switchCallbackHost->AsObject());
133 }
134 #endif
135 
SubscribeGnssStatus(const napi_env & env,const napi_ref & handlerRef,sptr<GnssStatusCallbackNapi> & gnssStatusCallbackHost)136 void SubscribeGnssStatus(const napi_env& env, const napi_ref& handlerRef,
137     sptr<GnssStatusCallbackNapi>& gnssStatusCallbackHost)
138 {
139     gnssStatusCallbackHost->SetEnv(env);
140     gnssStatusCallbackHost->SetHandleCb(handlerRef);
141     g_locatorProxy->RegisterGnssStatusCallback(gnssStatusCallbackHost->AsObject(), DEFAULT_UID);
142 }
143 
144 #ifdef ENABLE_NAPI_MANAGER
SubscribeGnssStatusV9(const napi_env & env,const napi_ref & handlerRef,sptr<GnssStatusCallbackNapi> & gnssStatusCallbackHost)145 LocationErrCode SubscribeGnssStatusV9(const napi_env& env, const napi_ref& handlerRef,
146     sptr<GnssStatusCallbackNapi>& gnssStatusCallbackHost)
147 {
148     LocationErrCode errorCode = CheckLocationSwitchEnable();
149     if (errorCode != ERRCODE_SUCCESS) {
150         return errorCode;
151     }
152     gnssStatusCallbackHost->SetEnv(env);
153     gnssStatusCallbackHost->SetHandleCb(handlerRef);
154     return g_locatorProxy->RegisterGnssStatusCallbackV9(gnssStatusCallbackHost->AsObject());
155 }
156 #endif
157 
SubscribeNmeaMessage(const napi_env & env,const napi_ref & handlerRef,sptr<NmeaMessageCallbackNapi> & nmeaMessageCallbackHost)158 void SubscribeNmeaMessage(const napi_env& env, const napi_ref& handlerRef,
159     sptr<NmeaMessageCallbackNapi>& nmeaMessageCallbackHost)
160 {
161     nmeaMessageCallbackHost->SetEnv(env);
162     nmeaMessageCallbackHost->SetHandleCb(handlerRef);
163     g_locatorProxy->RegisterNmeaMessageCallback(nmeaMessageCallbackHost->AsObject(), DEFAULT_UID);
164 }
165 
166 #ifdef ENABLE_NAPI_MANAGER
SubscribeNmeaMessageV9(const napi_env & env,const napi_ref & handlerRef,sptr<NmeaMessageCallbackNapi> & nmeaMessageCallbackHost)167 LocationErrCode SubscribeNmeaMessageV9(const napi_env& env, const napi_ref& handlerRef,
168     sptr<NmeaMessageCallbackNapi>& nmeaMessageCallbackHost)
169 {
170     LocationErrCode errorCode = CheckLocationSwitchEnable();
171     if (errorCode != ERRCODE_SUCCESS) {
172         return errorCode;
173     }
174     nmeaMessageCallbackHost->SetEnv(env);
175     nmeaMessageCallbackHost->SetHandleCb(handlerRef);
176     return g_locatorProxy->RegisterNmeaMessageCallbackV9(nmeaMessageCallbackHost->AsObject());
177 }
178 #endif
179 
UnSubscribeLocationServiceState(sptr<LocationSwitchCallbackNapi> & switchCallbackHost)180 void UnSubscribeLocationServiceState(sptr<LocationSwitchCallbackNapi>& switchCallbackHost)
181 {
182     LBSLOGD(LOCATION_NAPI, "UnSubscribeLocationServiceState");
183     g_locatorProxy->UnregisterSwitchCallback(switchCallbackHost->AsObject());
184 }
185 
186 #ifdef ENABLE_NAPI_MANAGER
UnSubscribeLocationServiceStateV9(sptr<LocationSwitchCallbackNapi> & switchCallbackHost)187 LocationErrCode UnSubscribeLocationServiceStateV9(sptr<LocationSwitchCallbackNapi>& switchCallbackHost)
188 {
189     LBSLOGD(LOCATION_NAPI, "UnSubscribeLocationServiceStateV9");
190     return g_locatorProxy->UnregisterSwitchCallbackV9(switchCallbackHost->AsObject());
191 }
192 #endif
193 
UnSubscribeGnssStatus(sptr<GnssStatusCallbackNapi> & gnssStatusCallbackHost)194 void UnSubscribeGnssStatus(sptr<GnssStatusCallbackNapi>& gnssStatusCallbackHost)
195 {
196     LBSLOGD(LOCATION_NAPI, "UnSubscribeGnssStatus");
197     g_locatorProxy->UnregisterGnssStatusCallback(gnssStatusCallbackHost->AsObject());
198 }
199 
200 #ifdef ENABLE_NAPI_MANAGER
UnSubscribeGnssStatusV9(sptr<GnssStatusCallbackNapi> & gnssStatusCallbackHost)201 LocationErrCode UnSubscribeGnssStatusV9(sptr<GnssStatusCallbackNapi>& gnssStatusCallbackHost)
202 {
203     LBSLOGD(LOCATION_NAPI, "UnSubscribeGnssStatusV9");
204     return g_locatorProxy->UnregisterGnssStatusCallbackV9(gnssStatusCallbackHost->AsObject());
205 }
206 #endif
207 
UnSubscribeNmeaMessage(sptr<NmeaMessageCallbackNapi> & nmeaMessageCallbackHost)208 void UnSubscribeNmeaMessage(sptr<NmeaMessageCallbackNapi>& nmeaMessageCallbackHost)
209 {
210     LBSLOGD(LOCATION_NAPI, "UnSubscribeNmeaMessage");
211     g_locatorProxy->UnregisterNmeaMessageCallback(nmeaMessageCallbackHost->AsObject());
212 }
213 
214 #ifdef ENABLE_NAPI_MANAGER
UnSubscribeNmeaMessageV9(sptr<NmeaMessageCallbackNapi> & nmeaMessageCallbackHost)215 LocationErrCode UnSubscribeNmeaMessageV9(sptr<NmeaMessageCallbackNapi>& nmeaMessageCallbackHost)
216 {
217     LBSLOGD(LOCATION_NAPI, "UnSubscribeNmeaMessageV9");
218     return g_locatorProxy->UnregisterNmeaMessageCallbackV9(nmeaMessageCallbackHost->AsObject());
219 }
220 #endif
221 
SubscribeLocationChange(const napi_env & env,const napi_value & object,const napi_ref & handlerRef,sptr<LocatorCallbackNapi> & locatorCallbackHost)222 void SubscribeLocationChange(const napi_env& env, const napi_value& object,
223     const napi_ref& handlerRef, sptr<LocatorCallbackNapi>& locatorCallbackHost)
224 {
225     auto locatorCallback = sptr<ILocatorCallback>(locatorCallbackHost);
226     locatorCallbackHost->SetFixNumber(0);
227     locatorCallbackHost->SetEnv(env);
228     locatorCallbackHost->SetHandleCb(handlerRef);
229     auto requestConfig = std::make_unique<RequestConfig>();
230     JsObjToLocationRequest(env, object, requestConfig);
231     g_locatorProxy->StartLocating(requestConfig, locatorCallback);
232 }
233 
234 #ifdef ENABLE_NAPI_MANAGER
SubscribeLocationChangeV9(const napi_env & env,const napi_value & object,const napi_ref & handlerRef,sptr<LocatorCallbackNapi> & locatorCallbackHost)235 LocationErrCode SubscribeLocationChangeV9(const napi_env& env, const napi_value& object,
236     const napi_ref& handlerRef, sptr<LocatorCallbackNapi>& locatorCallbackHost)
237 {
238     LocationErrCode errorCode = CheckLocationSwitchEnable();
239     if (errorCode != ERRCODE_SUCCESS) {
240         return errorCode;
241     }
242     auto locatorCallback = sptr<ILocatorCallback>(locatorCallbackHost);
243     locatorCallbackHost->SetFixNumber(0);
244     locatorCallbackHost->SetEnv(env);
245     locatorCallbackHost->SetHandleCb(handlerRef);
246     auto requestConfig = std::make_unique<RequestConfig>();
247     JsObjToLocationRequest(env, object, requestConfig);
248     if (!IsRequestConfigValid(requestConfig)) {
249         return ERRCODE_INVALID_PARAM;
250     }
251     return g_locatorProxy->StartLocatingV9(requestConfig, locatorCallback);
252 }
253 #endif
254 
SubscribeCountryCodeChange(const napi_env & env,const napi_ref & handlerRef,sptr<CountryCodeCallbackNapi> & callbackHost)255 void SubscribeCountryCodeChange(const napi_env& env,
256     const napi_ref& handlerRef, sptr<CountryCodeCallbackNapi>& callbackHost)
257 {
258     auto callbackPtr = sptr<ICountryCodeCallback>(callbackHost);
259     callbackHost->SetEnv(env);
260     callbackHost->SetCallback(handlerRef);
261     g_locatorProxy->RegisterCountryCodeCallback(callbackPtr->AsObject(), DEFAULT_UID);
262 }
263 
264 #ifdef ENABLE_NAPI_MANAGER
SubscribeCountryCodeChangeV9(const napi_env & env,const napi_ref & handlerRef,sptr<CountryCodeCallbackNapi> & callbackHost)265 LocationErrCode SubscribeCountryCodeChangeV9(const napi_env& env,
266     const napi_ref& handlerRef, sptr<CountryCodeCallbackNapi>& callbackHost)
267 {
268     auto callbackPtr = sptr<ICountryCodeCallback>(callbackHost);
269     callbackHost->SetEnv(env);
270     callbackHost->SetCallback(handlerRef);
271     return g_locatorProxy->RegisterCountryCodeCallbackV9(callbackPtr->AsObject());
272 }
273 #endif
274 
275 #ifdef ENABLE_NAPI_MANAGER
SubscribeLocatingRequiredDataChange(const napi_env & env,const napi_value & object,const napi_ref & handlerRef,sptr<LocatingRequiredDataCallbackNapi> & locatingCallbackHost)276 LocationErrCode SubscribeLocatingRequiredDataChange(const napi_env& env, const napi_value& object,
277     const napi_ref& handlerRef, sptr<LocatingRequiredDataCallbackNapi>& locatingCallbackHost)
278 {
279     auto callbackPtr = sptr<ILocatingRequiredDataCallback>(locatingCallbackHost);
280     locatingCallbackHost->SetEnv(env);
281     locatingCallbackHost->SetHandleCb(handlerRef);
282     std::unique_ptr<LocatingRequiredDataConfig> dataConfig = std::make_unique<LocatingRequiredDataConfig>();
283     JsObjToLocatingRequiredDataConfig(env, object, dataConfig);
284     return g_locatorProxy->RegisterLocatingRequiredDataCallback(dataConfig, callbackPtr);
285 }
286 
SubscribeLocationError(const napi_env & env,const napi_ref & handlerRef,sptr<LocationErrorCallbackNapi> & locationErrorCallbackHost)287 LocationErrCode SubscribeLocationError(const napi_env& env,
288     const napi_ref& handlerRef, sptr<LocationErrorCallbackNapi>& locationErrorCallbackHost)
289 {
290     locationErrorCallbackHost->SetEnv(env);
291     locationErrorCallbackHost->SetHandleCb(handlerRef);
292     auto locationErrorCallback = sptr<ILocatorCallback>(locationErrorCallbackHost);
293     return g_locatorProxy->SubscribeLocationError(locationErrorCallback);
294 }
295 #endif
296 
UnsubscribeCountryCodeChange(sptr<CountryCodeCallbackNapi> & callbackHost)297 void UnsubscribeCountryCodeChange(sptr<CountryCodeCallbackNapi>& callbackHost)
298 {
299     LBSLOGD(LOCATION_NAPI, "UnsubscribeCountryCodeChange");
300     g_locatorProxy->UnregisterCountryCodeCallback(callbackHost->AsObject());
301 }
302 
303 #ifdef ENABLE_NAPI_MANAGER
UnsubscribeCountryCodeChangeV9(sptr<CountryCodeCallbackNapi> & callbackHost)304 LocationErrCode UnsubscribeCountryCodeChangeV9(sptr<CountryCodeCallbackNapi>& callbackHost)
305 {
306     LBSLOGD(LOCATION_NAPI, "UnsubscribeCountryCodeChangeV9");
307     return g_locatorProxy->UnregisterCountryCodeCallbackV9(callbackHost->AsObject());
308 }
309 #endif
310 
SubscribeCacheLocationChange(const napi_env & env,const napi_value & object,const napi_ref & handlerRef,sptr<CachedLocationsCallbackNapi> & cachedCallbackHost)311 void SubscribeCacheLocationChange(const napi_env& env, const napi_value& object,
312     const napi_ref& handlerRef, sptr<CachedLocationsCallbackNapi>& cachedCallbackHost)
313 {
314     auto cachedCallback = sptr<ICachedLocationsCallback>(cachedCallbackHost);
315     cachedCallbackHost->SetEnv(env);
316     cachedCallbackHost->SetHandleCb(handlerRef);
317     JsObjToCachedLocationRequest(env, object, g_cachedRequest);
318     g_locatorProxy->RegisterCachedLocationCallback(g_cachedRequest, cachedCallback);
319 }
320 
321 #ifdef ENABLE_NAPI_MANAGER
SubscribeCacheLocationChangeV9(const napi_env & env,const napi_value & object,const napi_ref & handlerRef,sptr<CachedLocationsCallbackNapi> & cachedCallbackHost)322 LocationErrCode SubscribeCacheLocationChangeV9(const napi_env& env, const napi_value& object,
323     const napi_ref& handlerRef, sptr<CachedLocationsCallbackNapi>& cachedCallbackHost)
324 {
325     LocationErrCode errorCode = CheckLocationSwitchEnable();
326     if (errorCode != ERRCODE_SUCCESS) {
327         return errorCode;
328     }
329     auto cachedCallback = sptr<ICachedLocationsCallback>(cachedCallbackHost);
330     cachedCallbackHost->SetEnv(env);
331     cachedCallbackHost->SetHandleCb(handlerRef);
332     JsObjToCachedLocationRequest(env, object, g_cachedRequest);
333     g_locatorProxy->RegisterCachedLocationCallbackV9(g_cachedRequest, cachedCallback);
334     return ERRCODE_NOT_SUPPORTED;
335 }
336 #endif
337 
SubscribeFenceStatusChange(const napi_env & env,const napi_value & object,const napi_value & handler)338 void SubscribeFenceStatusChange(const napi_env& env, const napi_value& object, const napi_value& handler)
339 {
340     AbilityRuntime::WantAgent::WantAgent *wantAgent = nullptr;
341     napi_unwrap(env, handler, (void **)&wantAgent);
342     if (wantAgent == nullptr) {
343         LBSLOGE(LOCATION_NAPI, "wantAgent is nullptr");
344         return;
345     }
346     std::shared_ptr<GeofenceRequest> fenceRequest = std::make_shared<GeofenceRequest>();
347     fenceRequest->SetWantAgent(*wantAgent);
348     JsObjToGeoFenceRequest(env, object, fenceRequest);
349     g_geofenceProxy->AddFenceV9(fenceRequest);
350 }
351 
352 #ifdef ENABLE_NAPI_MANAGER
SubscribeFenceStatusChangeV9(const napi_env & env,const napi_value & object,const napi_value & handler)353 LocationErrCode SubscribeFenceStatusChangeV9(const napi_env& env, const napi_value& object, const napi_value& handler)
354 {
355     LocationErrCode errorCode = CheckLocationSwitchEnable();
356     if (errorCode != ERRCODE_SUCCESS) {
357         return errorCode;
358     }
359     AbilityRuntime::WantAgent::WantAgent *wantAgent = nullptr;
360     napi_unwrap(env, handler, (void **)&wantAgent);
361     if (wantAgent == nullptr) {
362         LBSLOGE(LOCATION_NAPI, "wantAgent is nullptr");
363         return ERRCODE_INVALID_PARAM;
364     }
365     std::shared_ptr<GeofenceRequest> fenceRequest = std::make_shared<GeofenceRequest>();
366     fenceRequest->SetWantAgent(*wantAgent);
367     JsObjToGeoFenceRequest(env, object, fenceRequest);
368     LocationErrCode errCode = g_geofenceProxy->AddFenceV9(fenceRequest);
369     return errCode;
370 }
371 #endif
372 
UnSubscribeFenceStatusChange(const napi_env & env,const napi_value & object,const napi_value & handler)373 void UnSubscribeFenceStatusChange(const napi_env& env, const napi_value& object, const napi_value& handler)
374 {
375     AbilityRuntime::WantAgent::WantAgent *wantAgent = nullptr;
376     napi_unwrap(env, handler, (void **)&wantAgent);
377     if (wantAgent == nullptr) {
378         LBSLOGE(LOCATION_NAPI, "wantAgent is nullptr");
379         return;
380     }
381     std::shared_ptr<GeofenceRequest> fenceRequest = std::make_shared<GeofenceRequest>();
382     fenceRequest->SetWantAgent(*wantAgent);
383     JsObjToGeoFenceRequest(env, object, fenceRequest);
384     g_geofenceProxy->RemoveFenceV9(fenceRequest);
385 }
386 
387 #ifdef ENABLE_NAPI_MANAGER
UnSubscribeFenceStatusChangeV9(const napi_env & env,const napi_value & object,const napi_value & handler)388 LocationErrCode UnSubscribeFenceStatusChangeV9(const napi_env& env, const napi_value& object, const napi_value& handler)
389 {
390     AbilityRuntime::WantAgent::WantAgent *wantAgent = nullptr;
391     napi_unwrap(env, handler, (void **)&wantAgent);
392     if (wantAgent == nullptr) {
393         LBSLOGE(LOCATION_NAPI, "wantAgent is nullptr");
394         return ERRCODE_INVALID_PARAM;
395     }
396     std::shared_ptr<GeofenceRequest> fenceRequest = std::make_shared<GeofenceRequest>();
397     fenceRequest->SetWantAgent(*wantAgent);
398     JsObjToGeoFenceRequest(env, object, fenceRequest);
399     return g_geofenceProxy->RemoveFenceV9(fenceRequest);
400 }
401 #endif
402 
403 #ifdef ENABLE_NAPI_MANAGER
UnSubscribeLocatingRequiredDataChange(sptr<LocatingRequiredDataCallbackNapi> & callbackHost)404 LocationErrCode UnSubscribeLocatingRequiredDataChange(sptr<LocatingRequiredDataCallbackNapi>& callbackHost)
405 {
406     LBSLOGD(LOCATION_NAPI, "%{public}s start", __func__);
407     auto callbackPtr = sptr<ILocatingRequiredDataCallback>(callbackHost);
408     return g_locatorProxy->UnRegisterLocatingRequiredDataCallback(callbackPtr);
409 }
410 #endif
411 
GenerateExecuteContext(SingleLocationAsyncContext * context)412 void GenerateExecuteContext(SingleLocationAsyncContext* context)
413 {
414     if (context == nullptr) {
415         return;
416     }
417     auto callbackHost = context->callbackHost_;
418     if (g_locatorProxy->IsLocationEnabled() && callbackHost != nullptr) {
419         auto callbackPtr = sptr<ILocatorCallback>(callbackHost);
420 #ifdef ENABLE_NAPI_MANAGER
421         LocationErrCode errorCode = g_locatorProxy->StartLocatingV9(context->request_, callbackPtr);
422         context->errCode = errorCode;
423         if (errorCode != ERRCODE_SUCCESS) {
424             callbackHost->SetCount(0);
425         }
426 #else
427         g_locatorProxy->StartLocating(context->request_, callbackPtr);
428 #endif
429         if (context->timeout_ > DEFAULT_TIMEOUT_30S) {
430             callbackHost->Wait(DEFAULT_TIMEOUT_30S);
431             if (callbackHost->GetSingleLocation() == nullptr) {
432                 callbackHost->Wait(context->timeout_ - DEFAULT_TIMEOUT_30S);
433             }
434         } else {
435             callbackHost->Wait(context->timeout_);
436         }
437         g_locatorProxy->StopLocating(callbackPtr);
438         if (callbackHost->GetCount() != 0 && callbackHost->GetSingleLocation() == nullptr) {
439             std::unique_ptr<Location> location = nullptr;
440 #ifdef ENABLE_NAPI_MANAGER
441             g_locatorProxy->GetCachedLocationV9(location);
442 #else
443             location = g_locatorProxy->GetCachedLocation();
444 #endif
445             int64_t curTime = CommonUtils::GetCurrentTimeStamp();
446             if (location != nullptr &&
447                 (curTime - location->GetTimeStamp() / MILLI_PER_SEC) <= LASTLOCATION_CACHED_TIME) {
448                 callbackHost->SetSingleLocation(location);
449             } else {
450                 context->errCode = ERRCODE_LOCATING_FAIL;
451             }
452         }
453         callbackHost->SetCount(1);
454 #ifndef ENABLE_NAPI_MANAGER
455     } else {
456         context->errCode = LOCATION_SWITCH_ERROR;
457 #endif
458     }
459 }
460 
GenerateCompleteContext(SingleLocationAsyncContext * context)461 void GenerateCompleteContext(SingleLocationAsyncContext* context)
462 {
463     if (context == nullptr) {
464         return;
465     }
466     NAPI_CALL_RETURN_VOID(context->env, napi_create_object(context->env, &context->result[PARAM1]));
467     auto callbackHost = context->callbackHost_;
468     if (callbackHost != nullptr && callbackHost->GetSingleLocation() != nullptr) {
469         std::unique_ptr<Location> location = std::make_unique<Location>(*callbackHost->GetSingleLocation());
470         LocationToJs(context->env, location, context->result[PARAM1]);
471     } else {
472         LBSLOGE(LOCATOR_STANDARD, "m_singleLocation is nullptr!");
473     }
474     if (context->callbackHost_) {
475         context->callbackHost_ = nullptr;
476     }
477 }
478 
CreateSingleLocationAsyncContext(const napi_env & env,std::unique_ptr<RequestConfig> & config,sptr<LocatorCallbackNapi> callback)479 SingleLocationAsyncContext* CreateSingleLocationAsyncContext(const napi_env& env,
480     std::unique_ptr<RequestConfig>& config, sptr<LocatorCallbackNapi> callback)
481 {
482     auto asyncContext = new (std::nothrow) SingleLocationAsyncContext(env);
483     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
484     NAPI_CALL(env, napi_create_string_latin1(env, "GetCurrentLocation",
485         NAPI_AUTO_LENGTH, &asyncContext->resourceName));
486     asyncContext->timeout_ = config->GetTimeOut();
487     asyncContext->callbackHost_ = callback;
488     asyncContext->request_ = std::move(config);
489     asyncContext->executeFunc = [&](void* data) -> void {
490         if (data == nullptr) {
491             LBSLOGE(LOCATOR_STANDARD, "data is nullptr!");
492             return;
493         }
494         auto context = static_cast<SingleLocationAsyncContext*>(data);
495         GenerateExecuteContext(context);
496     };
497     asyncContext->completeFunc = [&](void* data) -> void {
498         if (data == nullptr) {
499             LBSLOGE(LOCATOR_STANDARD, "data is nullptr!");
500             return;
501         }
502         auto context = static_cast<SingleLocationAsyncContext*>(data);
503         GenerateCompleteContext(context);
504         LBSLOGD(LOCATOR_STANDARD, "Push single location to client");
505     };
506     return asyncContext;
507 }
508 
GetObjectArgsNum(const napi_env & env,const size_t argc,const napi_value * argv)509 int GetObjectArgsNum(const napi_env& env, const size_t argc, const napi_value* argv)
510 {
511     napi_valuetype valueType = napi_undefined;
512     int objectArgsNum = PARAM0;
513     if (argc == PARAM0) {
514         objectArgsNum = PARAM0;
515     } else if (argc == PARAM1) {
516         NAPI_CALL_BASE(env, napi_typeof(env, argv[PARAM0], &valueType), objectArgsNum);
517         if (valueType == napi_object) {
518             objectArgsNum = PARAM1;
519         } else if (valueType == napi_function) {
520             objectArgsNum = PARAM0;
521         }
522     } else if (argc == PARAM2) {
523         objectArgsNum = PARAM1;
524     } else {
525         LBSLOGD(LOCATION_NAPI, "argc of GetCurrentLocation is wrong.");
526     }
527     return objectArgsNum;
528 }
529 
CreateRequestConfig(const napi_env & env,const napi_value * argv,const size_t & objectArgsNum)530 std::unique_ptr<RequestConfig> CreateRequestConfig(const napi_env& env,
531     const napi_value* argv, const size_t& objectArgsNum)
532 {
533     auto requestConfig = std::make_unique<RequestConfig>();
534     if (objectArgsNum > 0) {
535         JsObjToCurrentLocationRequest(env, argv[objectArgsNum - 1], requestConfig);
536     } else {
537         requestConfig->SetPriority(PRIORITY_FAST_FIRST_FIX);
538     }
539     requestConfig->SetFixNumber(1);
540     return requestConfig;
541 }
542 
CreateSingleLocationCallbackHost()543 sptr<LocatorCallbackNapi> CreateSingleLocationCallbackHost()
544 {
545     auto callbackHost =
546         sptr<LocatorCallbackNapi>(new (std::nothrow) LocatorCallbackNapi());
547     if (callbackHost) {
548         callbackHost->SetFixNumber(1);
549     }
550     return callbackHost;
551 }
552 
RequestLocationOnce(const napi_env & env,const size_t argc,const napi_value * argv)553 napi_value RequestLocationOnce(const napi_env& env, const size_t argc, const napi_value* argv)
554 {
555     size_t objectArgsNum = 0;
556 
557     objectArgsNum = static_cast<size_t>(GetObjectArgsNum(env, argc, argv));
558     auto requestConfig = CreateRequestConfig(env, argv, objectArgsNum);
559     NAPI_ASSERT(env, requestConfig != nullptr, "requestConfig is null.");
560     auto singleLocatorCallbackHost = CreateSingleLocationCallbackHost();
561     NAPI_ASSERT(env, singleLocatorCallbackHost != nullptr, "callbackHost is null.");
562 
563     auto asyncContext = CreateSingleLocationAsyncContext(env, requestConfig, singleLocatorCallbackHost);
564     NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
565     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
566 }
567 
568 #ifdef ENABLE_NAPI_MANAGER
RequestLocationOnceV9(const napi_env & env,const size_t argc,const napi_value * argv)569 napi_value RequestLocationOnceV9(const napi_env& env, const size_t argc, const napi_value* argv)
570 {
571     size_t objectArgsNum = 0;
572     objectArgsNum = static_cast<size_t>(GetObjectArgsNum(env, argc, argv));
573     auto requestConfig = CreateRequestConfig(env, argv, objectArgsNum);
574     if (!IsRequestConfigValid(requestConfig)) {
575         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
576         return UndefinedNapiValue(env);
577     }
578     auto singleLocatorCallbackHost = CreateSingleLocationCallbackHost();
579     if (singleLocatorCallbackHost == nullptr) {
580         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
581         return UndefinedNapiValue(env);
582     }
583     singleLocatorCallbackHost->SetLocationPriority(GetCurrentLocationType(requestConfig));
584     LocationErrCode errorCode = CheckLocationSwitchEnable();
585     if (errorCode != ERRCODE_SUCCESS) {
586         HandleSyncErrCode(env, errorCode);
587         return UndefinedNapiValue(env);
588     }
589 
590     auto asyncContext = CreateSingleLocationAsyncContext(env, requestConfig, singleLocatorCallbackHost);
591     if (asyncContext == nullptr) {
592         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
593         return UndefinedNapiValue(env);
594     }
595     return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
596 }
597 #endif
598 
UnSubscribeLocationChange(sptr<ILocatorCallback> & callback)599 void UnSubscribeLocationChange(sptr<ILocatorCallback>& callback)
600 {
601     LBSLOGD(LOCATION_NAPI, "UnSubscribeLocationChange");
602     g_locatorProxy->StopLocating(callback);
603 }
604 
605 #ifdef ENABLE_NAPI_MANAGER
UnSubscribeLocationChangeV9(sptr<ILocatorCallback> & callback)606 LocationErrCode UnSubscribeLocationChangeV9(sptr<ILocatorCallback>& callback)
607 {
608     LBSLOGD(LOCATION_NAPI, "UnSubscribeLocationChangeV9");
609     return g_locatorProxy->StopLocatingV9(callback);
610 }
611 #endif
612 
UnSubscribeCacheLocationChange(sptr<ICachedLocationsCallback> & callback)613 void UnSubscribeCacheLocationChange(sptr<ICachedLocationsCallback>& callback)
614 {
615     LBSLOGD(LOCATION_NAPI, "UnSubscribeCacheLocationChange");
616     g_locatorProxy->UnregisterCachedLocationCallback(callback);
617 }
618 
619 #ifdef ENABLE_NAPI_MANAGER
UnSubscribeCacheLocationChangeV9(sptr<ICachedLocationsCallback> & callback)620 LocationErrCode UnSubscribeCacheLocationChangeV9(sptr<ICachedLocationsCallback>& callback)
621 {
622     LBSLOGD(LOCATION_NAPI, "UnSubscribeCacheLocationChangeV9");
623     g_locatorProxy->UnregisterCachedLocationCallbackV9(callback);
624     return ERRCODE_NOT_SUPPORTED;
625 }
626 
UnSubscribeLocationError(sptr<ILocatorCallback> & callback)627 LocationErrCode UnSubscribeLocationError(sptr<ILocatorCallback>& callback)
628 {
629     LBSLOGD(LOCATION_NAPI, "UnSubscribeLocationError");
630     return g_locatorProxy->UnSubscribeLocationError(callback);
631 }
632 #endif
633 
IsCallbackEquals(const napi_env & env,const napi_value & handler,const napi_ref & savedCallback)634 bool IsCallbackEquals(const napi_env& env, const napi_value& handler, const napi_ref& savedCallback)
635 {
636     napi_value handlerTemp = nullptr;
637     if (savedCallback == nullptr || handler == nullptr) {
638         return false;
639     }
640     NAPI_CALL_BASE(env, napi_get_reference_value(env, savedCallback, &handlerTemp), false);
641     bool isEqual = false;
642     NAPI_CALL_BASE(env, napi_strict_equals(env, handlerTemp, handler, &isEqual), false);
643     return isEqual;
644 }
645 
OnLocationServiceStateCallback(const napi_env & env,const size_t argc,const napi_value * argv)646 bool OnLocationServiceStateCallback(const napi_env& env, const size_t argc, const napi_value* argv)
647 {
648 #ifdef ENABLE_NAPI_MANAGER
649     if (argc != PARAM2) {
650         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
651         return false;
652     }
653     if (!CheckIfParamIsFunctionType(env, argv[PARAM1])) {
654         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
655         return false;
656     }
657 #else
658     NAPI_ASSERT_BASE(env, argc == PARAM2, "number of parameters is wrong", INPUT_PARAMS_ERROR);
659     NAPI_ASSERT_BASE(env, CheckIfParamIsFunctionType(env, argv[PARAM1]),
660         "callback should be function, mismatch for param.", INPUT_PARAMS_ERROR);
661 #endif
662     if (g_switchCallbacks.IsCallbackInMap(env, argv[PARAM1])) {
663         LBSLOGE(LOCATION_NAPI, "This request already exists");
664         return false;
665     }
666     auto switchCallbackHost =
667         sptr<LocationSwitchCallbackNapi>(new (std::nothrow) LocationSwitchCallbackNapi());
668     if (switchCallbackHost != nullptr) {
669         napi_ref handlerRef = nullptr;
670         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM1], 1, &handlerRef), false);
671 #ifdef ENABLE_NAPI_MANAGER
672         LocationErrCode errorCode = SubscribeLocationServiceStateV9(env, handlerRef, switchCallbackHost);
673         if (errorCode != ERRCODE_SUCCESS) {
674             HandleSyncErrCode(env, errorCode);
675             return false;
676         }
677 #else
678         SubscribeLocationServiceState(env, handlerRef, switchCallbackHost);
679 #endif
680         g_switchCallbacks.AddCallback(env, handlerRef, switchCallbackHost);
681     }
682     return true;
683 }
684 
OnCachedGnssLocationsReportingCallback(const napi_env & env,const size_t argc,const napi_value * argv)685 bool OnCachedGnssLocationsReportingCallback(const napi_env& env, const size_t argc, const napi_value* argv)
686 {
687 #ifdef ENABLE_NAPI_MANAGER
688     if (argc != PARAM3) {
689         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
690         return false;
691     }
692     napi_valuetype valueType;
693     NAPI_CALL_BASE(env, napi_typeof(env, argv[PARAM1], &valueType), false);
694     if (valueType != napi_object || !CheckIfParamIsFunctionType(env, argv[PARAM2])) {
695         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
696         return UndefinedNapiValue(env);
697     }
698 #else
699     NAPI_ASSERT_BASE(env, argc == PARAM3, "number of parameters is wrong", INPUT_PARAMS_ERROR);
700     NAPI_ASSERT_BASE(env, CheckIfParamIsFunctionType(env, argv[PARAM2]),
701         "callback should be function, mismatch for param.", INPUT_PARAMS_ERROR);
702 #endif
703 #ifndef ENABLE_NAPI_MANAGER
704     if (!g_locatorProxy->IsLocationEnabled()) {
705         LBSLOGE(LOCATION_NAPI, "location switch is off, just return.");
706         return false;
707     }
708 #endif
709     // the third params should be handler
710     if (g_cachedLocationCallbacks.IsCallbackInMap(env, argv[PARAM2])) {
711         LBSLOGE(LOCATION_NAPI, "This request already exists");
712         return false;
713     }
714     auto cachedCallbackHost =
715         sptr<CachedLocationsCallbackNapi>(new (std::nothrow) CachedLocationsCallbackNapi());
716     if (cachedCallbackHost != nullptr) {
717         napi_ref handlerRef = nullptr;
718         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM2], PARAM1, &handlerRef), false);
719 #ifdef ENABLE_NAPI_MANAGER
720         LocationErrCode errorCode = SubscribeCacheLocationChangeV9(env, argv[PARAM1], handlerRef, cachedCallbackHost);
721         if (errorCode != ERRCODE_SUCCESS) {
722             HandleSyncErrCode(env, errorCode);
723             return false;
724         }
725 #else
726         SubscribeCacheLocationChange(env, argv[PARAM1], handlerRef, cachedCallbackHost);
727 #endif
728         g_cachedLocationCallbacks.AddCallback(env, handlerRef, cachedCallbackHost);
729     }
730     return true;
731 }
732 
OnGnssStatusChangeCallback(const napi_env & env,const size_t argc,const napi_value * argv)733 bool OnGnssStatusChangeCallback(const napi_env& env, const size_t argc, const napi_value* argv)
734 {
735 #ifdef ENABLE_NAPI_MANAGER
736     if (argc != PARAM2) {
737         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
738         return false;
739     }
740     if (!CheckIfParamIsFunctionType(env, argv[PARAM1])) {
741         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
742         return UndefinedNapiValue(env);
743     }
744 #else
745     NAPI_ASSERT_BASE(env, argc == PARAM2, "number of parameters is wrong", INPUT_PARAMS_ERROR);
746     NAPI_ASSERT_BASE(env, CheckIfParamIsFunctionType(env, argv[PARAM1]),
747         "callback should be function, mismatch for param.", INPUT_PARAMS_ERROR);
748 #endif
749     if (g_gnssStatusInfoCallbacks.IsCallbackInMap(env, argv[PARAM1])) {
750         LBSLOGE(LOCATION_NAPI, "This request already exists");
751         return false;
752     }
753     auto gnssCallbackHost =
754         sptr<GnssStatusCallbackNapi>(new (std::nothrow) GnssStatusCallbackNapi());
755     if (gnssCallbackHost != nullptr) {
756         napi_ref handlerRef = nullptr;
757         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM1], PARAM1, &handlerRef), false);
758 #ifdef ENABLE_NAPI_MANAGER
759         LocationErrCode errorCode = SubscribeGnssStatusV9(env, handlerRef, gnssCallbackHost);
760         if (errorCode != ERRCODE_SUCCESS) {
761             HandleSyncErrCode(env, errorCode);
762             return false;
763         }
764 #else
765         SubscribeGnssStatus(env, handlerRef, gnssCallbackHost);
766 #endif
767         g_gnssStatusInfoCallbacks.AddCallback(env, handlerRef, gnssCallbackHost);
768     }
769     return true;
770 }
771 
OnLocationChangeCallback(const napi_env & env,const size_t argc,const napi_value * argv)772 bool OnLocationChangeCallback(const napi_env& env, const size_t argc, const napi_value* argv)
773 {
774 #ifdef SUPPORT_JSSTACK
775     HiviewDFX::ReportXPowerJsStackSysEvent(env, "GNSS_STATE");
776 #endif
777 #ifdef ENABLE_NAPI_MANAGER
778     if (argc != PARAM3) {
779         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
780         return false;
781     }
782     napi_valuetype valueType;
783     NAPI_CALL_BASE(env, napi_typeof(env, argv[PARAM1], &valueType), false);
784     if (valueType != napi_object || !CheckIfParamIsFunctionType(env, argv[PARAM2])) {
785         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
786         return false;
787     }
788 #else
789     NAPI_ASSERT_BASE(env, argc == PARAM3, "number of parameters is wrong", INPUT_PARAMS_ERROR);
790     NAPI_ASSERT_BASE(env, CheckIfParamIsFunctionType(env, argv[PARAM2]),
791         "callback should be function, mismatch for param.", INPUT_PARAMS_ERROR);
792     if (!g_locatorProxy->IsLocationEnabled()) {
793         LBSLOGE(LOCATION_NAPI, "location switch is off, just return.");
794         return false;
795     }
796 #endif
797     // the third params should be handler
798     if (g_locationCallbacks.IsCallbackInMap(env, argv[PARAM2])) {
799         LBSLOGE(LOCATION_NAPI, "This request already exists");
800         return false;
801     }
802     auto locatorCallbackHost =
803         sptr<LocatorCallbackNapi>(new (std::nothrow) LocatorCallbackNapi());
804     if (locatorCallbackHost != nullptr) {
805         napi_ref handlerRef = nullptr;
806         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM2], 1, &handlerRef), false);
807         // argv[1]:request params, argv[2]:handler
808 #ifdef ENABLE_NAPI_MANAGER
809         LocationErrCode errorCode = SubscribeLocationChangeV9(env, argv[PARAM1], handlerRef, locatorCallbackHost);
810         if (errorCode != ERRCODE_SUCCESS) {
811             HandleSyncErrCode(env, errorCode);
812             return false;
813         }
814 #else
815         SubscribeLocationChange(env, argv[PARAM1], handlerRef, locatorCallbackHost);
816 #endif
817         g_locationCallbacks.AddCallback(env, handlerRef, locatorCallbackHost);
818     }
819     return true;
820 }
821 
OnNmeaMessageChangeCallback(const napi_env & env,const size_t argc,const napi_value * argv)822 bool OnNmeaMessageChangeCallback(const napi_env& env, const size_t argc, const napi_value* argv)
823 {
824 #ifdef ENABLE_NAPI_MANAGER
825     if (argc != PARAM2) {
826         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
827         return false;
828     }
829     if (!CheckIfParamIsFunctionType(env, argv[PARAM1])) {
830         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
831         return false;
832     }
833 #else
834     NAPI_ASSERT_BASE(env, argc == PARAM2, "number of parameters is wrong", INPUT_PARAMS_ERROR);
835     NAPI_ASSERT_BASE(env, CheckIfParamIsFunctionType(env, argv[PARAM1]),
836         "callback should be function, mismatch for param.", INPUT_PARAMS_ERROR);
837 #endif
838     if (g_nmeaCallbacks.IsCallbackInMap(env, argv[PARAM1])) {
839         LBSLOGE(LOCATION_NAPI, "This request already exists");
840         return false;
841     }
842     auto nmeaCallbackHost =
843         sptr<NmeaMessageCallbackNapi>(new (std::nothrow) NmeaMessageCallbackNapi());
844     if (nmeaCallbackHost != nullptr) {
845         napi_ref handlerRef = nullptr;
846         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM1], PARAM1, &handlerRef), false);
847 #ifdef ENABLE_NAPI_MANAGER
848         LocationErrCode errorCode = SubscribeNmeaMessageV9(env, handlerRef, nmeaCallbackHost);
849         if (errorCode != ERRCODE_SUCCESS) {
850             HandleSyncErrCode(env, errorCode);
851             return false;
852         }
853 #else
854         SubscribeNmeaMessage(env, handlerRef, nmeaCallbackHost);
855 #endif
856         g_nmeaCallbacks.AddCallback(env, handlerRef, nmeaCallbackHost);
857     }
858     return true;
859 }
860 
OnCountryCodeChangeCallback(const napi_env & env,const size_t argc,const napi_value * argv)861 bool OnCountryCodeChangeCallback(const napi_env& env, const size_t argc, const napi_value* argv)
862 {
863 #ifdef ENABLE_NAPI_MANAGER
864     if (argc != PARAM2) {
865         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
866         return false;
867     }
868     if (!CheckIfParamIsFunctionType(env, argv[PARAM1])) {
869         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
870         return false;
871     }
872 #else
873     NAPI_ASSERT_BASE(env, argc == PARAM2, "number of parameters is wrong", INPUT_PARAMS_ERROR);
874     NAPI_ASSERT_BASE(env, CheckIfParamIsFunctionType(env, argv[PARAM1]),
875         "callback should be function, mismatch for param.", INPUT_PARAMS_ERROR);
876 #endif
877     if (g_countryCodeCallbacks.IsCallbackInMap(env, argv[PARAM1])) {
878         LBSLOGE(LOCATION_NAPI, "This request already exists");
879         return false;
880     }
881     auto callbackHost =
882         sptr<CountryCodeCallbackNapi>(new (std::nothrow) CountryCodeCallbackNapi());
883     if (callbackHost) {
884         napi_ref handlerRef = nullptr;
885         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM1], 1, &handlerRef), false);
886 #ifdef ENABLE_NAPI_MANAGER
887         LocationErrCode errorCode = SubscribeCountryCodeChangeV9(env, handlerRef, callbackHost);
888         if (errorCode != ERRCODE_SUCCESS) {
889             HandleSyncErrCode(env, errorCode);
890             return false;
891         }
892 #else
893         SubscribeCountryCodeChange(env, handlerRef, callbackHost);
894 #endif
895         g_countryCodeCallbacks.AddCallback(env, handlerRef, callbackHost);
896     }
897     return true;
898 }
899 
OnFenceStatusChangeCallback(const napi_env & env,const size_t argc,const napi_value * argv)900 bool OnFenceStatusChangeCallback(const napi_env& env, const size_t argc, const napi_value* argv)
901 {
902 #ifdef ENABLE_NAPI_MANAGER
903     if (argc != PARAM3) {
904         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
905         return false;
906     }
907 #else
908     NAPI_ASSERT_BASE(env, argc == PARAM3, "number of parameters is wrong", INPUT_PARAMS_ERROR);
909     if (!g_locatorProxy->IsLocationEnabled()) {
910         LBSLOGE(LOCATION_NAPI, "location switch is off, just return.");
911         return false;
912     }
913 #endif
914     // the third params should be handler
915 #ifdef ENABLE_NAPI_MANAGER
916     LocationErrCode errorCode = SubscribeFenceStatusChangeV9(env, argv[PARAM1], argv[PARAM2]);
917     if (errorCode != ERRCODE_SUCCESS) {
918         HandleSyncErrCode(env, errorCode);
919         return false;
920     }
921 #else
922     SubscribeFenceStatusChange(env, argv[PARAM1], argv[PARAM2]);
923 #endif
924     return true;
925 }
926 
927 #ifdef ENABLE_NAPI_MANAGER
OnLocatingRequiredDataChangeCallback(const napi_env & env,const size_t argc,const napi_value * argv)928 bool OnLocatingRequiredDataChangeCallback(const napi_env& env, const size_t argc, const napi_value* argv)
929 {
930     if (argc != PARAM3) {
931         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
932         return false;
933     }
934     if (!CheckIfParamIsFunctionType(env, argv[PARAM2])) {
935         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
936         return false;
937     }
938     if (g_locatingRequiredDataCallbacks.IsCallbackInMap(env, argv[PARAM2])) {
939         LBSLOGE(LOCATION_NAPI, "%{public}s, This request already exists", __func__);
940         return false;
941     }
942     auto locatingCallbackHost =
943         sptr<LocatingRequiredDataCallbackNapi>(new (std::nothrow) LocatingRequiredDataCallbackNapi());
944     if (locatingCallbackHost != nullptr) {
945         napi_ref handlerRef = nullptr;
946         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM2], 1, &handlerRef), false);
947 
948         LocationErrCode errorCode =
949             SubscribeLocatingRequiredDataChange(env, argv[PARAM1], handlerRef, locatingCallbackHost);
950         if (errorCode != ERRCODE_SUCCESS) {
951             HandleSyncErrCode(env, errorCode);
952             return false;
953         }
954         g_locatingRequiredDataCallbacks.AddCallback(env, handlerRef, locatingCallbackHost);
955     }
956     return true;
957 }
958 #endif
959 
On(napi_env env,napi_callback_info cbinfo)960 napi_value On(napi_env env, napi_callback_info cbinfo)
961 {
962     InitOnFuncMap();
963     size_t argc = MAXIMUM_JS_PARAMS;
964     napi_value argv[MAXIMUM_JS_PARAMS] = {0};
965     napi_value thisVar = nullptr;
966     LBSLOGD(LOCATION_NAPI, "On function entry");
967     NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
968     napi_valuetype eventName = napi_undefined;
969     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &eventName));
970 #ifdef ENABLE_NAPI_MANAGER
971     if (eventName != napi_string) {
972         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
973         return UndefinedNapiValue(env);
974     }
975 #else
976     NAPI_ASSERT(env, eventName == napi_string, "type mismatch for parameter 1");
977 #endif
978     NAPI_ASSERT(env, g_locatorProxy != nullptr, "locator instance is null.");
979 
980     char type[64] = {0}; // max length
981     size_t typeLen = 0;
982     NAPI_CALL(env, napi_get_value_string_utf8(env, argv[PARAM0], type, sizeof(type), &typeLen));
983     std::string event = type;
984     LBSLOGD(LOCATION_NAPI, "Subscribe event: %{public}s", event.c_str());
985     std::unique_lock<std::mutex> lock(g_FuncMapMutex);
986     auto onCallbackFunc = g_onFuncMap.find(event);
987     if (onCallbackFunc != g_onFuncMap.end() && onCallbackFunc->second != nullptr) {
988         auto memberFunc = onCallbackFunc->second;
989         (*memberFunc)(env, argc, argv);
990     }
991     return UndefinedNapiValue(env);
992 }
993 
OffAllLocationServiceStateCallback(const napi_env & env)994 bool OffAllLocationServiceStateCallback(const napi_env& env)
995 {
996     std::map<napi_env, std::map<napi_ref, sptr<LocationSwitchCallbackNapi>>> callbackMap =
997         g_switchCallbacks.GetCallbackMap();
998     auto iter = callbackMap.find(env);
999     if (iter == callbackMap.end()) {
1000         return false;
1001     }
1002     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
1003         auto callbackHost = innerIter->second;
1004         if (callbackHost == nullptr) {
1005             continue;
1006         }
1007 #ifdef ENABLE_NAPI_MANAGER
1008         LocationErrCode errorCode = UnSubscribeLocationServiceStateV9(callbackHost);
1009         if (errorCode != ERRCODE_SUCCESS) {
1010             HandleSyncErrCode(env, errorCode);
1011             return false;
1012         }
1013 #else
1014         UnSubscribeLocationServiceState(callbackHost);
1015 #endif
1016         callbackHost->DeleteHandler();
1017         callbackHost = nullptr;
1018     }
1019     g_switchCallbacks.DeleteCallbackByEnv(env);
1020     return true;
1021 }
1022 
OffAllLocationChangeCallback(const napi_env & env)1023 bool OffAllLocationChangeCallback(const napi_env& env)
1024 {
1025     std::map<napi_env, std::map<napi_ref, sptr<LocatorCallbackNapi>>> callbackMap =
1026         g_locationCallbacks.GetCallbackMap();
1027     auto iter = callbackMap.find(env);
1028     if (iter == callbackMap.end()) {
1029         return false;
1030     }
1031     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
1032         auto callbackHost = innerIter->second;
1033         if (callbackHost == nullptr) {
1034             continue;
1035         }
1036         auto locatorCallback = sptr<ILocatorCallback>(callbackHost);
1037 #ifdef ENABLE_NAPI_MANAGER
1038         LocationErrCode errorCode = UnSubscribeLocationChangeV9(locatorCallback);
1039         if (errorCode != ERRCODE_SUCCESS) {
1040             HandleSyncErrCode(env, errorCode);
1041             return false;
1042         }
1043 #else
1044         UnSubscribeLocationChange(locatorCallback);
1045 #endif
1046         callbackHost->DeleteAllCallbacks();
1047         callbackHost = nullptr;
1048     }
1049     g_locationCallbacks.DeleteCallbackByEnv(env);
1050     return true;
1051 }
1052 
OffAllGnssStatusChangeCallback(const napi_env & env)1053 bool OffAllGnssStatusChangeCallback(const napi_env& env)
1054 {
1055     std::map<napi_env, std::map<napi_ref, sptr<GnssStatusCallbackNapi>>> callbackMap =
1056         g_gnssStatusInfoCallbacks.GetCallbackMap();
1057     auto iter = callbackMap.find(env);
1058     if (iter == callbackMap.end()) {
1059         return false;
1060     }
1061     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
1062         auto callbackHost = innerIter->second;
1063         if (callbackHost == nullptr) {
1064             continue;
1065         }
1066 #ifdef ENABLE_NAPI_MANAGER
1067         LocationErrCode errorCode = UnSubscribeGnssStatusV9(callbackHost);
1068         if (errorCode != ERRCODE_SUCCESS) {
1069             HandleSyncErrCode(env, errorCode);
1070             return false;
1071         }
1072 #else
1073         UnSubscribeGnssStatus(callbackHost);
1074 #endif
1075         callbackHost->DeleteHandler();
1076         callbackHost = nullptr;
1077     }
1078     g_gnssStatusInfoCallbacks.DeleteCallbackByEnv(env);
1079     return true;
1080 }
1081 
OffAllNmeaMessageChangeCallback(const napi_env & env)1082 bool OffAllNmeaMessageChangeCallback(const napi_env& env)
1083 {
1084     std::map<napi_env, std::map<napi_ref, sptr<NmeaMessageCallbackNapi>>> callbackMap =
1085         g_nmeaCallbacks.GetCallbackMap();
1086     auto iter = callbackMap.find(env);
1087     if (iter == callbackMap.end()) {
1088         return false;
1089     }
1090     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
1091         auto callbackHost = innerIter->second;
1092         if (callbackHost == nullptr) {
1093             continue;
1094         }
1095 #ifdef ENABLE_NAPI_MANAGER
1096         LocationErrCode errorCode = UnSubscribeNmeaMessageV9(callbackHost);
1097         if (errorCode != ERRCODE_SUCCESS) {
1098             HandleSyncErrCode(env, errorCode);
1099             return false;
1100         }
1101 #else
1102         UnSubscribeNmeaMessage(callbackHost);
1103 #endif
1104         callbackHost->DeleteHandler();
1105         callbackHost = nullptr;
1106     }
1107     g_nmeaCallbacks.DeleteCallbackByEnv(env);
1108     return true;
1109 }
1110 
OffAllCachedGnssLocationsReportingCallback(const napi_env & env)1111 bool OffAllCachedGnssLocationsReportingCallback(const napi_env& env)
1112 {
1113     std::map<napi_env, std::map<napi_ref, sptr<CachedLocationsCallbackNapi>>> callbackMap =
1114         g_cachedLocationCallbacks.GetCallbackMap();
1115     auto iter = callbackMap.find(env);
1116     if (iter == callbackMap.end()) {
1117 #ifdef ENABLE_NAPI_MANAGER
1118         HandleSyncErrCode(env, ERRCODE_NOT_SUPPORTED);
1119 #endif
1120         return false;
1121     }
1122     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
1123         auto callbackHost = innerIter->second;
1124         if (callbackHost == nullptr) {
1125             continue;
1126         }
1127         auto cachedCallback = sptr<ICachedLocationsCallback>(callbackHost);
1128 #ifdef ENABLE_NAPI_MANAGER
1129         LocationErrCode errorCode = UnSubscribeCacheLocationChangeV9(cachedCallback);
1130         if (errorCode != ERRCODE_SUCCESS) {
1131             HandleSyncErrCode(env, errorCode);
1132             return false;
1133         }
1134 #else
1135         UnSubscribeCacheLocationChange(cachedCallback);
1136 #endif
1137         callbackHost->DeleteHandler();
1138         callbackHost = nullptr;
1139     }
1140     g_cachedLocationCallbacks.DeleteCallbackByEnv(env);
1141     return true;
1142 }
1143 
OffAllCountryCodeChangeCallback(const napi_env & env)1144 bool OffAllCountryCodeChangeCallback(const napi_env& env)
1145 {
1146     std::map<napi_env, std::map<napi_ref, sptr<CountryCodeCallbackNapi>>> callbackMap =
1147         g_countryCodeCallbacks.GetCallbackMap();
1148     auto iter = callbackMap.find(env);
1149     if (iter == callbackMap.end()) {
1150         return false;
1151     }
1152     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
1153         auto callbackHost = innerIter->second;
1154         if (callbackHost == nullptr) {
1155             continue;
1156         }
1157 #ifdef ENABLE_NAPI_MANAGER
1158         LocationErrCode errorCode = UnsubscribeCountryCodeChangeV9(callbackHost);
1159         if (errorCode != ERRCODE_SUCCESS) {
1160             HandleSyncErrCode(env, errorCode);
1161             return false;
1162         }
1163 #else
1164         UnsubscribeCountryCodeChange(callbackHost);
1165 #endif
1166         callbackHost->DeleteHandler();
1167         callbackHost = nullptr;
1168     }
1169     g_countryCodeCallbacks.DeleteCallbackByEnv(env);
1170     return true;
1171 }
1172 
1173 #ifdef ENABLE_NAPI_MANAGER
OffAllLocatingRequiredDataChangeCallback(const napi_env & env)1174 bool OffAllLocatingRequiredDataChangeCallback(const napi_env& env)
1175 {
1176     std::map<napi_env, std::map<napi_ref, sptr<LocatingRequiredDataCallbackNapi>>> callbackMap =
1177         g_locatingRequiredDataCallbacks.GetCallbackMap();
1178     auto iter = callbackMap.find(env);
1179     if (iter == callbackMap.end()) {
1180         return false;
1181     }
1182     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
1183         auto callbackHost = innerIter->second;
1184         if (callbackHost == nullptr) {
1185             continue;
1186         }
1187         LocationErrCode errorCode = UnSubscribeLocatingRequiredDataChange(callbackHost);
1188         if (errorCode != ERRCODE_SUCCESS) {
1189             HandleSyncErrCode(env, errorCode);
1190             return false;
1191         }
1192         callbackHost->DeleteHandler();
1193         callbackHost = nullptr;
1194     }
1195     g_locatingRequiredDataCallbacks.DeleteCallbackByEnv(env);
1196     return true;
1197 }
1198 #endif
1199 
OffLocationServiceStateCallback(const napi_env & env,const napi_value & handler)1200 bool OffLocationServiceStateCallback(const napi_env& env, const napi_value& handler)
1201 {
1202     auto switchCallbackHost = g_switchCallbacks.GetCallbackPtr(env, handler);
1203     if (switchCallbackHost) {
1204 #ifdef ENABLE_NAPI_MANAGER
1205         LocationErrCode errorCode = UnSubscribeLocationServiceStateV9(switchCallbackHost);
1206         if (errorCode != ERRCODE_SUCCESS) {
1207             HandleSyncErrCode(env, errorCode);
1208             return false;
1209         }
1210 #else
1211         UnSubscribeLocationServiceState(switchCallbackHost);
1212 #endif
1213         g_switchCallbacks.DeleteCallback(env, handler);
1214         switchCallbackHost->DeleteHandler();
1215         switchCallbackHost = nullptr;
1216         return true;
1217     }
1218     return false;
1219 }
1220 
OffLocationChangeCallback(const napi_env & env,const napi_value & handler)1221 bool OffLocationChangeCallback(const napi_env& env, const napi_value& handler)
1222 {
1223     auto locatorCallbackHost = g_locationCallbacks.GetCallbackPtr(env, handler);
1224     if (locatorCallbackHost) {
1225         auto locatorCallback = sptr<ILocatorCallback>(locatorCallbackHost);
1226 #ifdef ENABLE_NAPI_MANAGER
1227         LocationErrCode errorCode = UnSubscribeLocationChangeV9(locatorCallback);
1228         if (errorCode != ERRCODE_SUCCESS) {
1229             HandleSyncErrCode(env, errorCode);
1230             return false;
1231         }
1232 #else
1233         UnSubscribeLocationChange(locatorCallback);
1234 #endif
1235         g_locationCallbacks.DeleteCallback(env, handler);
1236         locatorCallbackHost->DeleteAllCallbacks();
1237         locatorCallbackHost = nullptr;
1238         return true;
1239     }
1240     return false;
1241 }
1242 
OffGnssStatusChangeCallback(const napi_env & env,const napi_value & handler)1243 bool OffGnssStatusChangeCallback(const napi_env& env, const napi_value& handler)
1244 {
1245     auto gnssCallbackHost = g_gnssStatusInfoCallbacks.GetCallbackPtr(env, handler);
1246     if (gnssCallbackHost) {
1247 #ifdef ENABLE_NAPI_MANAGER
1248         LocationErrCode errorCode = UnSubscribeGnssStatusV9(gnssCallbackHost);
1249         if (errorCode != ERRCODE_SUCCESS) {
1250             HandleSyncErrCode(env, errorCode);
1251             return false;
1252         }
1253 #else
1254         UnSubscribeGnssStatus(gnssCallbackHost);
1255 #endif
1256         g_gnssStatusInfoCallbacks.DeleteCallback(env, handler);
1257         gnssCallbackHost->DeleteHandler();
1258         gnssCallbackHost = nullptr;
1259         return true;
1260     }
1261     return false;
1262 }
1263 
OffNmeaMessageChangeCallback(const napi_env & env,const napi_value & handler)1264 bool OffNmeaMessageChangeCallback(const napi_env& env, const napi_value& handler)
1265 {
1266     auto nmeaCallbackHost = g_nmeaCallbacks.GetCallbackPtr(env, handler);
1267     if (nmeaCallbackHost) {
1268 #ifdef ENABLE_NAPI_MANAGER
1269         LocationErrCode ret = UnSubscribeNmeaMessageV9(nmeaCallbackHost);
1270         if (ret != ERRCODE_SUCCESS) {
1271             HandleSyncErrCode(env, ret);
1272             return false;
1273         }
1274 #else
1275         UnSubscribeNmeaMessage(nmeaCallbackHost);
1276 #endif
1277         g_nmeaCallbacks.DeleteCallback(env, handler);
1278         nmeaCallbackHost->DeleteHandler();
1279         nmeaCallbackHost = nullptr;
1280         return true;
1281     }
1282     return false;
1283 }
1284 
OffCachedGnssLocationsReportingCallback(const napi_env & env,const napi_value & handler)1285 bool OffCachedGnssLocationsReportingCallback(const napi_env& env, const napi_value& handler)
1286 {
1287     auto cachedCallbackHost = g_cachedLocationCallbacks.GetCallbackPtr(env, handler);
1288     if (cachedCallbackHost) {
1289         auto cachedCallback = sptr<ICachedLocationsCallback>(cachedCallbackHost);
1290 #ifdef ENABLE_NAPI_MANAGER
1291         LocationErrCode errorCode = UnSubscribeCacheLocationChangeV9(cachedCallback);
1292         if (errorCode != ERRCODE_SUCCESS) {
1293             HandleSyncErrCode(env, errorCode);
1294             return false;
1295         }
1296 #else
1297         UnSubscribeCacheLocationChange(cachedCallback);
1298 #endif
1299         g_cachedLocationCallbacks.DeleteCallback(env, handler);
1300         cachedCallbackHost->DeleteHandler();
1301         cachedCallbackHost = nullptr;
1302         return true;
1303     } else {
1304         LBSLOGI(LOCATION_NAPI, "%{public}s, the callback is not in the map", __func__);
1305 #ifdef ENABLE_NAPI_MANAGER
1306         HandleSyncErrCode(env, ERRCODE_NOT_SUPPORTED);
1307 #endif
1308     }
1309     return false;
1310 }
1311 
OffCountryCodeChangeCallback(const napi_env & env,const napi_value & handler)1312 bool OffCountryCodeChangeCallback(const napi_env& env, const napi_value& handler)
1313 {
1314     auto callbackHost = g_countryCodeCallbacks.GetCallbackPtr(env, handler);
1315     if (callbackHost) {
1316 #ifdef ENABLE_NAPI_MANAGER
1317         LocationErrCode errorCode = UnsubscribeCountryCodeChangeV9(callbackHost);
1318         if (errorCode != ERRCODE_SUCCESS) {
1319             HandleSyncErrCode(env, errorCode);
1320             return false;
1321         }
1322 #else
1323         UnsubscribeCountryCodeChange(callbackHost);
1324 #endif
1325         g_countryCodeCallbacks.DeleteCallback(env, handler);
1326         callbackHost->DeleteHandler();
1327         callbackHost = nullptr;
1328         return true;
1329     }
1330     return false;
1331 }
1332 
1333 #ifdef ENABLE_NAPI_MANAGER
OffLocatingRequiredDataChangeCallback(const napi_env & env,const napi_value & handler)1334 bool OffLocatingRequiredDataChangeCallback(const napi_env& env, const napi_value& handler)
1335 {
1336     auto callbackHost = g_locatingRequiredDataCallbacks.GetCallbackPtr(env, handler);
1337     if (callbackHost) {
1338         LocationErrCode errorCode = UnSubscribeLocatingRequiredDataChange(callbackHost);
1339         if (errorCode != ERRCODE_SUCCESS) {
1340             HandleSyncErrCode(env, errorCode);
1341             return false;
1342         }
1343         g_locatingRequiredDataCallbacks.DeleteCallback(env, handler);
1344         callbackHost->DeleteHandler();
1345         callbackHost = nullptr;
1346         return true;
1347     }
1348     return false;
1349 }
1350 #endif
1351 
VerifyOffFuncParam(napi_env env,napi_callback_info cbinfo,size_t & argc)1352 bool VerifyOffFuncParam(napi_env env, napi_callback_info cbinfo, size_t& argc)
1353 {
1354     napi_value argv[MAXIMUM_JS_PARAMS] = {0};
1355     napi_valuetype valueType[PARAM3] = {napi_undefined};
1356     napi_value thisVar = nullptr;
1357     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr), false);
1358     NAPI_ASSERT_BASE(env, g_locatorProxy != nullptr, "locator instance is null.", false);
1359     argc = (argc > PARAM3) ? PARAM3 : argc;
1360     if (argc > 0) {
1361         for (int i = (int)(argc - 1); i >= 0; i--) {
1362             NAPI_CALL_BASE(env, napi_typeof(env, argv[i], &valueType[i]), false);
1363             /* If the type of the last input parameter is incorrect, ignore it. */
1364             if (valueType[i] != napi_function && valueType[i] != napi_object && valueType[i] != napi_string &&
1365                 i == (int)(argc - 1)) {
1366                 argc--;
1367             }
1368         }
1369     }
1370     if (argc == PARAM3 && valueType[argc - 1] != napi_object) {
1371         argc--;
1372     }
1373     if (argc == PARAM2 && valueType[argc - 1] != napi_function) {
1374         argc--;
1375     }
1376     if (argc < PARAM1 || valueType[PARAM0] != napi_string ||
1377         (argc == PARAM2 && valueType[PARAM1] != napi_function) ||
1378         (argc == PARAM3 && valueType[PARAM1] != napi_object && valueType[PARAM2] != napi_object)) {
1379 #ifdef ENABLE_NAPI_MANAGER
1380         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1381 #else
1382         NAPI_ASSERT_BASE(env, false, "ERRCODE_INVALID_PARAM", false);
1383 #endif
1384         return false;
1385     }
1386     return true;
1387 }
1388 
Off(napi_env env,napi_callback_info cbinfo)1389 napi_value Off(napi_env env, napi_callback_info cbinfo)
1390 {
1391     LBSLOGD(LOCATION_NAPI, "Off function entry");
1392     InitOffFuncMap();
1393 
1394     size_t argc = MAXIMUM_JS_PARAMS;
1395     napi_value argv[MAXIMUM_JS_PARAMS] = {0};
1396     napi_value thisVar = nullptr;
1397     NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
1398 
1399     if (!VerifyOffFuncParam(env, cbinfo, argc)) {
1400         LBSLOGE(LOCATION_NAPI, "VerifyOffFuncParam fail");
1401         return UndefinedNapiValue(env);
1402     }
1403 
1404     char type[64] = {0};
1405     size_t typeLen = 0;
1406     NAPI_CALL(env, napi_get_value_string_utf8(env, argv[PARAM0], type, sizeof(type), &typeLen));
1407     std::string event = type;
1408     LBSLOGD(LOCATION_NAPI, "Unsubscribe event: %{public}s", event.c_str());
1409     if (argc == PARAM1) {
1410         std::unique_lock<std::mutex> lock(g_FuncMapMutex);
1411         auto offAllCallbackFunc = g_offAllFuncMap.find(event);
1412         if (offAllCallbackFunc != g_offAllFuncMap.end() && offAllCallbackFunc->second != nullptr) {
1413             auto memberFunc = offAllCallbackFunc->second;
1414             (*memberFunc)(env);
1415         }
1416     } else if (argc == PARAM2) {
1417         std::unique_lock<std::mutex> lock(g_FuncMapMutex);
1418         auto offCallbackFunc = g_offFuncMap.find(event);
1419         if (offCallbackFunc != g_offFuncMap.end() && offCallbackFunc->second != nullptr) {
1420             auto singleMemberFunc = offCallbackFunc->second;
1421             (*singleMemberFunc)(env, argv[PARAM1]);
1422         }
1423 #ifdef ENABLE_NAPI_MANAGER
1424     } else if (argc == PARAM3 && event == "gnssFenceStatusChange") {
1425         LocationErrCode errorCode = UnSubscribeFenceStatusChangeV9(env, argv[PARAM1], argv[PARAM2]);
1426         if (errorCode != ERRCODE_SUCCESS) {
1427             HandleSyncErrCode(env, errorCode);
1428         }
1429     } else {
1430         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1431 #else
1432     } else if (argc == PARAM3 && event == "fenceStatusChange") {
1433         UnSubscribeFenceStatusChange(env, argv[PARAM1], argv[PARAM2]);
1434 #endif
1435     }
1436     return UndefinedNapiValue(env);
1437 }
1438 
GetCurrentLocation(napi_env env,napi_callback_info cbinfo)1439 napi_value GetCurrentLocation(napi_env env, napi_callback_info cbinfo)
1440 {
1441     size_t argc = MAXIMUM_JS_PARAMS;
1442     napi_value argv[MAXIMUM_JS_PARAMS] = {0};
1443     napi_valuetype valueType[MAXIMUM_JS_PARAMS] = {napi_undefined};
1444     napi_value thisVar = nullptr;
1445     NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
1446     NAPI_ASSERT(env, g_locatorProxy != nullptr, "locator instance is null.");
1447     LBSLOGD(LOCATION_NAPI, "GetCurrentLocation enter");
1448 #ifdef SUPPORT_JSSTACK
1449     HiviewDFX::ReportXPowerJsStackSysEvent(env, "GNSS_STATE");
1450 #endif
1451     argc = (argc > PARAM2) ? PARAM2 : argc;
1452     if (argc > 0) {
1453         for (int i = (int)(argc - 1); i >= 0; i--) {
1454             NAPI_CALL(env, napi_typeof(env, argv[i], &valueType[i]));
1455             /* If the type of the last input parameter is incorrect, ignore it. */
1456             if (valueType[i] != napi_function && valueType[i] != napi_object &&
1457                 i == (int)(argc - 1)) {
1458                 argc--;
1459             }
1460         }
1461     }
1462     if (argc == PARAM2) {
1463         if (valueType[PARAM1] != napi_function) {
1464             argc--;
1465         }
1466 #ifdef ENABLE_NAPI_MANAGER
1467         else if (valueType[PARAM0] != napi_object) {
1468             HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1469             return UndefinedNapiValue(env);
1470         }
1471 #else
1472         else {
1473             NAPI_ASSERT(env, valueType[PARAM0] == napi_object, "type mismatch for parameter 1");
1474         }
1475 #endif
1476     }
1477     if (argc == PARAM1) {
1478         if (valueType[PARAM0] != napi_function && valueType[PARAM0] != napi_object) {
1479             argc--;
1480         }
1481     }
1482 #ifdef ENABLE_NAPI_MANAGER
1483     return RequestLocationOnceV9(env, argc, argv);
1484 #else
1485     return RequestLocationOnce(env, argc, argv);
1486 #endif
1487 }
1488 
1489 #ifdef ENABLE_NAPI_MANAGER
CheckLocationSwitchEnable()1490 LocationErrCode CheckLocationSwitchEnable()
1491 {
1492     bool isEnabled = false;
1493     LocationErrCode errorCode = g_locatorProxy->IsLocationEnabledV9(isEnabled);
1494     if (errorCode != ERRCODE_SUCCESS) {
1495         return errorCode;
1496     }
1497     if (!isEnabled) {
1498         return ERRCODE_SWITCH_OFF;
1499     }
1500     return ERRCODE_SUCCESS;
1501 }
1502 #endif
1503 
IsRequestConfigValid(std::unique_ptr<RequestConfig> & config)1504 bool IsRequestConfigValid(std::unique_ptr<RequestConfig>& config)
1505 {
1506     if (config == nullptr) {
1507         return false;
1508     }
1509     if ((config->GetScenario() > SCENE_NO_POWER || config->GetScenario() < SCENE_UNSET) &&
1510         (config->GetScenario() > LOCATION_SCENE_RIDE ||
1511         config->GetScenario() < LOCATION_SCENE_NAVIGATION) &&
1512         (config->GetScenario() > LOCATION_SCENE_NO_POWER_CONSUMPTION ||
1513         config->GetScenario() < LOCATION_SCENE_HIGH_POWER_CONSUMPTION)) {
1514         return false;
1515     }
1516     if ((config->GetPriority() > PRIORITY_FAST_FIRST_FIX || config->GetPriority() < PRIORITY_UNSET) &&
1517         (config->GetPriority() > LOCATION_PRIORITY_LOCATING_SPEED ||
1518         config->GetPriority() < LOCATION_PRIORITY_ACCURACY)) {
1519         return false;
1520     }
1521     if (config->GetTimeOut() < MIN_TIMEOUTMS_FOR_LOCATIONONCE) {
1522         return false;
1523     }
1524     if (config->GetTimeInterval() < 0) {
1525         return false;
1526     }
1527     if (config->GetDistanceInterval() < 0) {
1528         return false;
1529     }
1530     if (config->GetMaxAccuracy() < 0) {
1531         return false;
1532     }
1533     return true;
1534 }
1535 
1536 #ifdef ENABLE_NAPI_MANAGER
OnLocationErrorCallback(const napi_env & env,const size_t argc,const napi_value * argv)1537 bool OnLocationErrorCallback(const napi_env& env, const size_t argc, const napi_value* argv)
1538 {
1539     if (argc != PARAM2) {
1540         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1541         LBSLOGE(LOCATION_NAPI, "ERRCODE_INVALID_PARAM");
1542         return false;
1543     }
1544     if (!CheckIfParamIsFunctionType(env, argv[PARAM1])) {
1545         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
1546         LBSLOGE(LOCATION_NAPI, "ERRCODE_INVALID_PARAM");
1547         return false;
1548     }
1549     // the third params should be handler
1550     if (g_locationErrorCallbackHosts.IsCallbackInMap(env, argv[PARAM1])) {
1551         LBSLOGE(LOCATION_NAPI, "This request already exists");
1552         return false;
1553     }
1554     auto locationErrorCallbackHost =
1555         sptr<LocationErrorCallbackNapi>(new (std::nothrow) LocationErrorCallbackNapi());
1556     if (locationErrorCallbackHost != nullptr) {
1557         napi_ref handlerRef = nullptr;
1558         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM1], 1, &handlerRef), false);
1559         // argv[1]:request params, argv[2]:handler
1560         LocationErrCode errorCode = SubscribeLocationError(env, handlerRef, locationErrorCallbackHost);
1561         if (errorCode != ERRCODE_SUCCESS) {
1562             HandleSyncErrCode(env, errorCode);
1563             return false;
1564         }
1565         g_locationErrorCallbackHosts.AddCallback(env, handlerRef, locationErrorCallbackHost);
1566     }
1567     return true;
1568 }
1569 
OffLocationErrorCallback(const napi_env & env,const napi_value & handler)1570 bool OffLocationErrorCallback(const napi_env& env, const napi_value& handler)
1571 {
1572     auto locationErrorCallbackHost = g_locationErrorCallbackHosts.GetCallbackPtr(env, handler);
1573     if (locationErrorCallbackHost) {
1574         auto locatorCallback = sptr<ILocatorCallback>(locationErrorCallbackHost);
1575         LocationErrCode errorCode = UnSubscribeLocationError(locatorCallback);
1576         if (errorCode != ERRCODE_SUCCESS) {
1577             HandleSyncErrCode(env, errorCode);
1578             return false;
1579         }
1580         g_locationErrorCallbackHosts.DeleteCallback(env, handler);
1581         locationErrorCallbackHost = nullptr;
1582         return true;
1583     }
1584     return false;
1585 }
1586 #endif
1587 
GetCurrentLocationType(std::unique_ptr<RequestConfig> & config)1588 int GetCurrentLocationType(std::unique_ptr<RequestConfig>& config)
1589 {
1590     if (config->GetPriority() == LOCATION_PRIORITY_ACCURACY ||
1591         (config->GetScenario() == SCENE_UNSET && config->GetPriority() == PRIORITY_ACCURACY) ||
1592         config->GetScenario() == SCENE_NAVIGATION ||
1593         config->GetScenario() == SCENE_TRAJECTORY_TRACKING ||
1594         config->GetScenario() == SCENE_CAR_HAILING) {
1595         return LOCATION_PRIORITY_ACCURACY;
1596     } else {
1597         return LOCATION_PRIORITY_LOCATING_SPEED;
1598     }
1599 }
1600 }  // namespace Location
1601 }  // namespace OHOS
1602