• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "locator_callback_host.h"
17 
18 #include "ipc_object_stub.h"
19 #include "ipc_skeleton.h"
20 #include "js_native_api.h"
21 #include "message_option.h"
22 #include "message_parcel.h"
23 #include "napi/native_common.h"
24 #include "uv.h"
25 
26 #include "common_utils.h"
27 #include "constant_definition.h"
28 #include "i_locator_callback.h"
29 #include "location.h"
30 #include "location_async_context.h"
31 #include "location_log.h"
32 #include "napi_util.h"
33 
34 namespace OHOS {
35 namespace Location {
LocatorCallbackHost()36 LocatorCallbackHost::LocatorCallbackHost()
37 {
38     env_ = nullptr;
39     handlerCb_ = nullptr;
40     successHandlerCb_ = nullptr;
41     failHandlerCb_ = nullptr;
42     completeHandlerCb_ = nullptr;
43     deferred_ = nullptr;
44     fixNumber_ = 0;
45     inHdArea_ = true;
46     singleLocation_ = nullptr;
47     InitLatch();
48 }
49 
InitLatch()50 void LocatorCallbackHost::InitLatch()
51 {
52     latch_ = new CountDownLatch();
53     latch_->SetCount(1);
54 }
55 
~LocatorCallbackHost()56 LocatorCallbackHost::~LocatorCallbackHost()
57 {
58     delete latch_;
59 }
60 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)61 int LocatorCallbackHost::OnRemoteRequest(uint32_t code,
62     MessageParcel& data, MessageParcel& reply, MessageOption& option)
63 {
64     if (data.ReadInterfaceToken() != GetDescriptor()) {
65         LBSLOGE(LOCATOR_CALLBACK, "invalid token.");
66         return -1;
67     }
68 
69     switch (code) {
70         case RECEIVE_LOCATION_INFO_EVENT: {
71             std::unique_ptr<Location> location = Location::Unmarshalling(data);
72             OnLocationReport(location);
73             if (location->GetLocationSourceType() == LocationSourceType::NETWORK_TYPE &&
74                 location->GetAdditionsMap()["inHdArea"] != "") {
75                 inHdArea_ = (location->GetAdditionsMap()["inHdArea"] == "true");
76             }
77             if (NeedSetSingleLocation(location)) {
78                 SetSingleLocation(location);
79             }
80             if (IfReportAccuracyLocation()) {
81                 CountDown();
82             }
83             break;
84         }
85         case RECEIVE_LOCATION_STATUS_EVENT: {
86             int status = data.ReadInt32();
87             OnLocatingStatusChange(status);
88             break;
89         }
90         case RECEIVE_ERROR_INFO_EVENT: {
91             int errorCode = data.ReadInt32();
92             LBSLOGI(LOCATOR_STANDARD, "CallbackSutb receive ERROR_EVENT. errorCode:%{public}d", errorCode);
93             if (errorCode == LOCATING_FAILED_INTERNET_ACCESS_FAILURE) {
94                 inHdArea_ = false;
95                 if (GetSingleLocation() != nullptr) {
96                     CountDown();
97                 }
98             } else {
99                 OnErrorReport(errorCode);
100             }
101             break;
102         }
103         default: {
104             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
105             break;
106         }
107     }
108     return 0;
109 }
110 
DoSendWork(uv_loop_s * & loop,uv_work_t * & work)111 void LocatorCallbackHost::DoSendWork(uv_loop_s*& loop, uv_work_t*& work)
112 {
113     uv_queue_work(loop, work, [](uv_work_t* work) {}, [](uv_work_t* work, int status) {
114         if (work == nullptr) {
115             return;
116         }
117         napi_handle_scope scope = nullptr;
118         auto context = static_cast<LocationAsyncContext*>(work->data);
119         if (context == nullptr) {
120             delete work;
121             return;
122         }
123         if (context->env == nullptr || context->loc == nullptr) {
124             delete context;
125             delete work;
126             return;
127         }
128         napi_open_handle_scope(context->env, &scope);
129         if (scope == nullptr) {
130             DELETE_SCOPE_CONTEXT_WORK(context->env, scope, context, work);
131             return;
132         }
133         napi_value jsEvent = nullptr;
134         CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_create_object(context->env, &jsEvent), scope, context, work);
135         if (context->callback[1]) {
136             SystemLocationToJs(context->env, context->loc, jsEvent);
137         } else {
138             LocationToJs(context->env, context->loc, jsEvent);
139         }
140         if (context->callback[0] != nullptr) {
141             napi_value undefine = nullptr;
142             napi_value handler = nullptr;
143             CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
144                 scope, context, work);
145             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
146                 napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
147             if (napi_call_function(context->env, nullptr, handler, 1, &jsEvent, &undefine) != napi_ok) {
148                 LBSLOGE(LOCATOR_CALLBACK, "Report location failed");
149             }
150         } else if (context->deferred != nullptr) {
151             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
152                 ((jsEvent != nullptr) ? napi_resolve_deferred(context->env, context->deferred, jsEvent) :
153                 napi_reject_deferred(context->env, context->deferred, jsEvent)),
154                 scope, context, work);
155         }
156         DELETE_SCOPE_CONTEXT_WORK(context->env, scope, context, work);
157     });
158 }
159 
DoSendErrorCode(uv_loop_s * & loop,uv_work_t * & work)160 void LocatorCallbackHost::DoSendErrorCode(uv_loop_s *&loop, uv_work_t *&work)
161 {
162     uv_queue_work(loop, work, [](uv_work_t *work) {},
163         [](uv_work_t *work, int status) {
164             AsyncContext *context = nullptr;
165             napi_handle_scope scope = nullptr;
166             if (work == nullptr) {
167                 LBSLOGE(LOCATOR_CALLBACK, "work is nullptr");
168                 return;
169             }
170             context = static_cast<AsyncContext *>(work->data);
171             if (context == nullptr || context->env == nullptr) {
172                 LBSLOGE(LOCATOR_CALLBACK, "context is nullptr");
173                 delete work;
174                 return;
175             }
176             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
177             if (scope == nullptr) {
178                 LBSLOGE(LOCATOR_CALLBACK, "scope is nullptr");
179                 delete context;
180                 delete work;
181                 return;
182             }
183             if (context->callback[FAIL_CALLBACK] != nullptr) {
184                 napi_value undefine;
185                 napi_value handler = nullptr;
186                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
187                     scope, context, work);
188                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
189                     napi_get_reference_value(context->env, context->callback[FAIL_CALLBACK], &handler),
190                     scope, context, work);
191                 std::string msg = GetErrorMsgByCode(context->errCode);
192                 CreateFailCallBackParams(*context, msg, context->errCode);
193                 if (napi_call_function(context->env, nullptr, handler, RESULT_SIZE,
194                     context->result, &undefine) != napi_ok) {
195                     LBSLOGE(LOCATOR_CALLBACK, "Report system error failed");
196                 }
197             }
198             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
199             delete context;
200             delete work;
201     });
202 }
203 
SendErrorCode(const int & errorCode)204 bool LocatorCallbackHost::SendErrorCode(const int& errorCode)
205 {
206     std::unique_lock<std::mutex> guard(mutex_);
207     if (!IsSystemGeoLocationApi() && !IsSingleLocationRequest()) {
208         LBSLOGE(LOCATOR_CALLBACK, "this is Callback type,cant send error msg.");
209         return false;
210     }
211     if (env_ == nullptr) {
212         LBSLOGE(LOCATOR_CALLBACK, "env_ is nullptr.");
213         return false;
214     }
215     uv_loop_s *loop = nullptr;
216     NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
217     if (loop == nullptr) {
218         LBSLOGE(LOCATOR_CALLBACK, "loop == nullptr.");
219         return false;
220     }
221     uv_work_t *work = new (std::nothrow) uv_work_t;
222     if (work == nullptr) {
223         LBSLOGE(LOCATOR_CALLBACK, "work == nullptr.");
224         return false;
225     }
226     AsyncContext *context = new (std::nothrow) AsyncContext(env_);
227     if (context == nullptr) {
228         LBSLOGE(LOCATOR_CALLBACK, "context == nullptr.");
229         delete work;
230         return false;
231     }
232     if (!InitContext(context)) {
233         LBSLOGE(LOCATOR_CALLBACK, "InitContext fail");
234     }
235     context->errCode = errorCode;
236     work->data = context;
237     DoSendErrorCode(loop, work);
238     return true;
239 }
240 
OnLocationReport(const std::unique_ptr<Location> & location)241 void LocatorCallbackHost::OnLocationReport(const std::unique_ptr<Location>& location)
242 {
243     std::unique_lock<std::mutex> guard(mutex_);
244     uv_loop_s *loop = nullptr;
245     if (env_ == nullptr) {
246         LBSLOGD(LOCATOR_CALLBACK, "env_ is nullptr.");
247         return;
248     }
249     NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop));
250     if (loop == nullptr) {
251         LBSLOGE(LOCATOR_CALLBACK, "loop == nullptr.");
252         return;
253     }
254     uv_work_t *work = new (std::nothrow) uv_work_t;
255     if (work == nullptr) {
256         LBSLOGE(LOCATOR_CALLBACK, "work == nullptr.");
257         return;
258     }
259     auto context = new (std::nothrow) LocationAsyncContext(env_);
260     if (context == nullptr) {
261         LBSLOGE(LOCATOR_CALLBACK, "context == nullptr.");
262         delete work;
263         return;
264     }
265     if (!InitContext(context)) {
266         LBSLOGE(LOCATOR_CALLBACK, "InitContext fail");
267     }
268     context->loc = std::make_unique<Location>(*location);
269     work->data = context;
270     DoSendWork(loop, work);
271 }
272 
OnLocatingStatusChange(const int status)273 void LocatorCallbackHost::OnLocatingStatusChange(const int status)
274 {
275 }
276 
OnErrorReport(const int errorCode)277 void LocatorCallbackHost::OnErrorReport(const int errorCode)
278 {
279     SendErrorCode(errorCode);
280 }
281 
DeleteAllCallbacks()282 void LocatorCallbackHost::DeleteAllCallbacks()
283 {
284     DeleteHandler();
285 }
286 
DeleteHandler()287 void LocatorCallbackHost::DeleteHandler()
288 {
289     LBSLOGD(LOCATOR_CALLBACK, "before DeleteHandler");
290     std::unique_lock<std::mutex> guard(mutex_);
291     if (env_ == nullptr) {
292         LBSLOGE(LOCATOR_CALLBACK, "env is nullptr.");
293         return;
294     }
295     auto context = new (std::nothrow) AsyncContext(env_);
296     if (context == nullptr) {
297         LBSLOGE(LOCATOR_CALLBACK, "context == nullptr.");
298         return;
299     }
300     if (!InitContext(context)) {
301         LBSLOGE(LOCATOR_CALLBACK, "InitContext fail");
302     }
303     DeleteQueueWork(context);
304     if (IsSystemGeoLocationApi()) {
305         successHandlerCb_ = nullptr;
306         failHandlerCb_ = nullptr;
307         completeHandlerCb_ = nullptr;
308     } else {
309         handlerCb_ = nullptr;
310     }
311 }
312 
IsSystemGeoLocationApi()313 bool LocatorCallbackHost::IsSystemGeoLocationApi()
314 {
315     return (successHandlerCb_ != nullptr) ? true : false;
316 }
317 
IsSingleLocationRequest()318 bool LocatorCallbackHost::IsSingleLocationRequest()
319 {
320     return (fixNumber_ == 1);
321 }
322 
CountDown()323 void LocatorCallbackHost::CountDown()
324 {
325     if (IsSingleLocationRequest() && latch_ != nullptr) {
326         latch_->CountDown();
327     }
328 }
329 
Wait(int time)330 void LocatorCallbackHost::Wait(int time)
331 {
332     if (IsSingleLocationRequest() && latch_ != nullptr) {
333         latch_->Wait(time);
334     }
335 }
336 
GetCount()337 int LocatorCallbackHost::GetCount()
338 {
339     if (IsSingleLocationRequest() && latch_ != nullptr) {
340         return latch_->GetCount();
341     }
342     return 0;
343 }
344 
SetCount(int count)345 void LocatorCallbackHost::SetCount(int count)
346 {
347     if (IsSingleLocationRequest() && latch_ != nullptr) {
348         return latch_->SetCount(count);
349     }
350 }
351 
NeedSetSingleLocation(const std::unique_ptr<Location> & location)352 bool LocatorCallbackHost::NeedSetSingleLocation(const std::unique_ptr<Location>& location)
353 {
354     if (locationPriority_ == LOCATION_PRIORITY_ACCURACY &&
355         singleLocation_ != nullptr &&
356         location->GetLocationSourceType() == LocationSourceType::NETWORK_TYPE) {
357         return false;
358     } else {
359         return true;
360     }
361 }
362 
IfReportAccuracyLocation()363 bool LocatorCallbackHost::IfReportAccuracyLocation()
364 {
365     if (locationPriority_ == LOCATION_PRIORITY_ACCURACY &&
366         ((singleLocation_->GetLocationSourceType() == LocationSourceType::GNSS_TYPE && inHdArea_) ||
367         singleLocation_->GetLocationSourceType() == LocationSourceType::NETWORK_TYPE)) {
368         return false;
369     } else {
370         return true;
371     }
372 }
373 
SetSingleLocation(const std::unique_ptr<Location> & location)374 void LocatorCallbackHost::SetSingleLocation(const std::unique_ptr<Location>& location)
375 {
376     std::unique_lock<std::mutex> guard(mutex_);
377     singleLocation_ = std::make_shared<Location>(*location);
378 }
379 } // namespace Location
380 } // namespace OHOS
381