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