• 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     singleLocation_ = nullptr;
46     InitLatch();
47 }
48 
InitLatch()49 void LocatorCallbackHost::InitLatch()
50 {
51     latch_ = new CountDownLatch();
52     latch_->SetCount(1);
53 }
54 
~LocatorCallbackHost()55 LocatorCallbackHost::~LocatorCallbackHost()
56 {
57     delete latch_;
58 }
59 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)60 int LocatorCallbackHost::OnRemoteRequest(uint32_t code,
61     MessageParcel& data, MessageParcel& reply, MessageOption& option)
62 {
63     if (data.ReadInterfaceToken() != GetDescriptor()) {
64         LBSLOGE(LOCATOR_CALLBACK, "invalid token.");
65         return -1;
66     }
67 
68     switch (code) {
69         case RECEIVE_LOCATION_INFO_EVENT: {
70             std::unique_ptr<Location> location = Location::Unmarshalling(data);
71             LBSLOGI(LOCATOR_STANDARD, "CallbackSutb receive LOCATION_EVENT.");
72             OnLocationReport(location);
73             std::unique_lock<std::mutex> guard(mutex_);
74             singleLocation_ = std::move(location);
75             CountDown();
76             break;
77         }
78         case RECEIVE_LOCATION_STATUS_EVENT: {
79             int status = data.ReadInt32();
80             LBSLOGI(LOCATOR_STANDARD, "CallbackSutb receive STATUS_EVENT. status:%{public}d", status);
81             OnLocatingStatusChange(status);
82             break;
83         }
84         case RECEIVE_ERROR_INFO_EVENT: {
85             int errorCode = data.ReadInt32();
86             LBSLOGI(LOCATOR_STANDARD, "CallbackSutb receive ERROR_EVENT. errorCode:%{public}d", errorCode);
87             OnErrorReport(errorCode);
88             break;
89         }
90         default: {
91             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
92             break;
93         }
94     }
95     return 0;
96 }
97 
DoSendWork(uv_loop_s * & loop,uv_work_t * & work)98 void LocatorCallbackHost::DoSendWork(uv_loop_s*& loop, uv_work_t*& work)
99 {
100     uv_queue_work(loop, work, [](uv_work_t* work) {}, [](uv_work_t* work, int status) {
101         if (work == nullptr) {
102             return;
103         }
104         napi_handle_scope scope = nullptr;
105         auto context = static_cast<LocationAsyncContext*>(work->data);
106         if (context == nullptr) {
107             delete work;
108             return;
109         }
110         if (context->env == nullptr || context->loc == nullptr) {
111             delete context;
112             delete work;
113             return;
114         }
115         napi_open_handle_scope(context->env, &scope);
116         if (scope == nullptr) {
117             DELETE_SCOPE_CONTEXT_WORK(context->env, scope, context, work);
118             return;
119         }
120         napi_value jsEvent = nullptr;
121         CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_create_object(context->env, &jsEvent), scope, context, work);
122         if (context->callback[1]) {
123             SystemLocationToJs(context->env, context->loc, jsEvent);
124         } else {
125             LocationToJs(context->env, context->loc, jsEvent);
126         }
127         if (context->callback[0] != nullptr) {
128             napi_value undefine = nullptr;
129             napi_value handler = nullptr;
130             CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
131                 scope, context, work);
132             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
133                 napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
134             if (napi_call_function(context->env, nullptr, handler, 1, &jsEvent, &undefine) != napi_ok) {
135                 LBSLOGE(LOCATOR_CALLBACK, "Report location failed");
136             }
137         } else if (context->deferred != nullptr) {
138             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
139                 ((jsEvent != nullptr) ? napi_resolve_deferred(context->env, context->deferred, jsEvent) :
140                 napi_reject_deferred(context->env, context->deferred, jsEvent)),
141                 scope, context, work);
142         }
143         DELETE_SCOPE_CONTEXT_WORK(context->env, scope, context, work);
144     });
145 }
146 
DoSendErrorCode(uv_loop_s * & loop,uv_work_t * & work)147 void LocatorCallbackHost::DoSendErrorCode(uv_loop_s *&loop, uv_work_t *&work)
148 {
149     uv_queue_work(loop, work, [](uv_work_t *work) {},
150         [](uv_work_t *work, int status) {
151             AsyncContext *context = nullptr;
152             napi_handle_scope scope = nullptr;
153             if (work == nullptr) {
154                 LBSLOGE(LOCATOR_CALLBACK, "work is nullptr");
155                 return;
156             }
157             context = static_cast<AsyncContext *>(work->data);
158             if (context == nullptr || context->env == nullptr) {
159                 LBSLOGE(LOCATOR_CALLBACK, "context is nullptr");
160                 delete work;
161                 return;
162             }
163             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
164             if (scope == nullptr) {
165                 LBSLOGE(LOCATOR_CALLBACK, "scope is nullptr");
166                 delete context;
167                 delete work;
168                 return;
169             }
170             if (context->callback[FAIL_CALLBACK] != nullptr) {
171                 napi_value undefine;
172                 napi_value handler = nullptr;
173                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
174                     scope, context, work);
175                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
176                     napi_get_reference_value(context->env, context->callback[FAIL_CALLBACK], &handler),
177                     scope, context, work);
178                 std::string msg = GetErrorMsgByCode(context->errCode);
179                 CreateFailCallBackParams(*context, msg, context->errCode);
180                 if (napi_call_function(context->env, nullptr, handler, RESULT_SIZE,
181                     context->result, &undefine) != napi_ok) {
182                     LBSLOGE(LOCATOR_CALLBACK, "Report system error failed");
183                 }
184             }
185             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
186             delete context;
187             delete work;
188     });
189 }
190 
SendErrorCode(const int & errorCode)191 bool LocatorCallbackHost::SendErrorCode(const int& errorCode)
192 {
193     std::unique_lock<std::mutex> guard(mutex_);
194     if (!IsSystemGeoLocationApi() && !IsSingleLocationRequest()) {
195         LBSLOGE(LOCATOR_CALLBACK, "this is Callback type,cant send error msg.");
196         return false;
197     }
198     if (env_ == nullptr) {
199         LBSLOGE(LOCATOR_CALLBACK, "env_ is nullptr.");
200         return false;
201     }
202     uv_loop_s *loop = nullptr;
203     NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
204     if (loop == nullptr) {
205         LBSLOGE(LOCATOR_CALLBACK, "loop == nullptr.");
206         return false;
207     }
208     uv_work_t *work = new (std::nothrow) uv_work_t;
209     if (work == nullptr) {
210         LBSLOGE(LOCATOR_CALLBACK, "work == nullptr.");
211         return false;
212     }
213     AsyncContext *context = new (std::nothrow) AsyncContext(env_);
214     if (context == nullptr) {
215         LBSLOGE(LOCATOR_CALLBACK, "context == nullptr.");
216         delete work;
217         return false;
218     }
219     if (!InitContext(context)) {
220         LBSLOGE(LOCATOR_CALLBACK, "InitContext fail");
221     }
222     context->errCode = errorCode;
223     work->data = context;
224     DoSendErrorCode(loop, work);
225     return true;
226 }
227 
OnLocationReport(const std::unique_ptr<Location> & location)228 void LocatorCallbackHost::OnLocationReport(const std::unique_ptr<Location>& location)
229 {
230     std::unique_lock<std::mutex> guard(mutex_);
231     uv_loop_s *loop = nullptr;
232     if (env_ == nullptr) {
233         LBSLOGE(LOCATOR_CALLBACK, "env_ is nullptr.");
234         return;
235     }
236     NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop));
237     if (loop == nullptr) {
238         LBSLOGE(LOCATOR_CALLBACK, "loop == nullptr.");
239         return;
240     }
241     uv_work_t *work = new (std::nothrow) uv_work_t;
242     if (work == nullptr) {
243         LBSLOGE(LOCATOR_CALLBACK, "work == nullptr.");
244         return;
245     }
246     auto context = new (std::nothrow) LocationAsyncContext(env_);
247     if (context == nullptr) {
248         LBSLOGE(LOCATOR_CALLBACK, "context == nullptr.");
249         delete work;
250         return;
251     }
252     if (!InitContext(context)) {
253         LBSLOGE(LOCATOR_CALLBACK, "InitContext fail");
254     }
255     context->loc = std::make_unique<Location>(*location);
256     work->data = context;
257     DoSendWork(loop, work);
258 }
259 
OnLocatingStatusChange(const int status)260 void LocatorCallbackHost::OnLocatingStatusChange(const int status)
261 {
262 }
263 
OnErrorReport(const int errorCode)264 void LocatorCallbackHost::OnErrorReport(const int errorCode)
265 {
266     SendErrorCode(errorCode);
267 }
268 
DeleteAllCallbacks()269 void LocatorCallbackHost::DeleteAllCallbacks()
270 {
271     DeleteHandler();
272 }
273 
DeleteHandler()274 void LocatorCallbackHost::DeleteHandler()
275 {
276     LBSLOGD(LOCATOR_CALLBACK, "before DeleteHandler");
277     std::unique_lock<std::mutex> guard(mutex_);
278     if (env_ == nullptr) {
279         LBSLOGE(LOCATOR_CALLBACK, "env is nullptr.");
280         return;
281     }
282     auto context = new (std::nothrow) AsyncContext(env_);
283     if (context == nullptr) {
284         LBSLOGE(LOCATOR_CALLBACK, "context == nullptr.");
285         return;
286     }
287     if (!InitContext(context)) {
288         LBSLOGE(LOCATOR_CALLBACK, "InitContext fail");
289     }
290     DeleteQueueWork(context);
291     if (IsSystemGeoLocationApi()) {
292         successHandlerCb_ = nullptr;
293         failHandlerCb_ = nullptr;
294         completeHandlerCb_ = nullptr;
295     } else {
296         handlerCb_ = nullptr;
297     }
298 }
299 
IsSystemGeoLocationApi()300 bool LocatorCallbackHost::IsSystemGeoLocationApi()
301 {
302     return (successHandlerCb_ != nullptr) ? true : false;
303 }
304 
IsSingleLocationRequest()305 bool LocatorCallbackHost::IsSingleLocationRequest()
306 {
307     return (fixNumber_ == 1);
308 }
309 
CountDown()310 void LocatorCallbackHost::CountDown()
311 {
312     if (IsSingleLocationRequest() && latch_ != nullptr) {
313         latch_->CountDown();
314     }
315 }
316 
Wait(int time)317 void LocatorCallbackHost::Wait(int time)
318 {
319     LBSLOGI(LOCATOR_CALLBACK, "Wait time:%{public}d", time);
320     if (IsSingleLocationRequest() && latch_ != nullptr) {
321         latch_->Wait(time);
322     }
323 }
324 
GetCount()325 int LocatorCallbackHost::GetCount()
326 {
327     if (IsSingleLocationRequest() && latch_ != nullptr) {
328         return latch_->GetCount();
329     }
330     return 0;
331 }
332 
SetCount(int count)333 void LocatorCallbackHost::SetCount(int count)
334 {
335     if (IsSingleLocationRequest() && latch_ != nullptr) {
336         return latch_->SetCount(count);
337     }
338 }
339 } // namespace Location
340 } // namespace OHOS
341