• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "locating_required_data_callback_napi.h"
16 
17 #include "ipc_skeleton.h"
18 #include "napi/native_common.h"
19 
20 #include "common_utils.h"
21 #include "location_log.h"
22 #include "napi_util.h"
23 
24 namespace OHOS {
25 namespace Location {
LocatingRequiredDataCallbackNapi()26 LocatingRequiredDataCallbackNapi::LocatingRequiredDataCallbackNapi()
27 {
28     env_ = nullptr;
29     handlerCb_ = nullptr;
30     remoteDied_ = false;
31     fixNumber_ = 0;
32     InitLatch();
33 }
34 
~LocatingRequiredDataCallbackNapi()35 LocatingRequiredDataCallbackNapi::~LocatingRequiredDataCallbackNapi()
36 {
37     if (latch_ != nullptr) {
38         delete latch_;
39         latch_ = nullptr;
40     }
41 }
42 
InitLatch()43 void LocatingRequiredDataCallbackNapi::InitLatch()
44 {
45     latch_ = new CountDownLatch();
46     latch_->SetCount(1);
47 }
48 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)49 int LocatingRequiredDataCallbackNapi::OnRemoteRequest(
50     uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
51 {
52     LBSLOGD(LOCATING_DATA_CALLBACK, "LocatingRequiredDataCallbackNapi::OnRemoteRequest!");
53     if (data.ReadInterfaceToken() != GetDescriptor()) {
54         LBSLOGE(LOCATING_DATA_CALLBACK, "invalid token.");
55         return -1;
56     }
57     if (remoteDied_) {
58         LBSLOGD(LOCATING_DATA_CALLBACK, "Failed to `%{public}s`,Remote service is died!", __func__);
59         return -1;
60     }
61 
62     switch (code) {
63         case RECEIVE_INFO_EVENT: {
64             int cnt = data.ReadInt32();
65             if (cnt > 0 && cnt <= MAXIMUM_LOCATING_REQUIRED_DATAS) {
66                 std::vector<std::shared_ptr<LocatingRequiredData>> res;
67                 for (int i = 0; i < cnt; i++) {
68                     res.push_back(LocatingRequiredData::Unmarshalling(data));
69                 }
70                 // update wifi info
71                 if (res[0]->GetType() == LocatingRequiredDataType::WIFI) {
72                     SetSingleResult(res);
73                 }
74                 OnLocatingDataChange(res);
75                 CountDown();
76             }
77             break;
78         }
79         default: {
80             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
81             break;
82         }
83     }
84     return 0;
85 }
86 
IsRemoteDied()87 bool LocatingRequiredDataCallbackNapi::IsRemoteDied()
88 {
89     return remoteDied_;
90 }
91 
Send(const std::vector<std::shared_ptr<LocatingRequiredData>> & data)92 bool LocatingRequiredDataCallbackNapi::Send(const std::vector<std::shared_ptr<LocatingRequiredData>>& data)
93 {
94     if (IsSingleLocationRequest()) {
95         return false;
96     }
97     std::unique_lock<std::mutex> guard(mutex_);
98     uv_loop_s *loop = nullptr;
99     NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
100     if (loop == nullptr) {
101         LBSLOGE(LOCATING_DATA_CALLBACK, "loop == nullptr.");
102         return false;
103     }
104     if (handlerCb_ == nullptr) {
105         LBSLOGE(LOCATING_DATA_CALLBACK, "handler is nullptr.");
106         return false;
107     }
108     uv_work_t *work = new (std::nothrow) uv_work_t;
109     if (work == nullptr) {
110         LBSLOGE(LOCATING_DATA_CALLBACK, "work == nullptr.");
111         return false;
112     }
113     LocatingRequiredDataAsyncContext *context = new (std::nothrow) LocatingRequiredDataAsyncContext(env_);
114     if (context == nullptr) {
115         LBSLOGE(LOCATING_DATA_CALLBACK, "context == nullptr.");
116         delete work;
117         return false;
118     }
119     if (!InitContext(context)) {
120         LBSLOGE(LOCATING_DATA_CALLBACK, "InitContext fail");
121         return false;
122     }
123     context->locatingRequiredDataList_ = data;
124     work->data = context;
125     UvQueueWork(loop, work);
126     return true;
127 }
128 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)129 void LocatingRequiredDataCallbackNapi::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
130 {
131     uv_queue_work(
132         loop,
133         work,
134         [](uv_work_t *work) {},
135         [](uv_work_t *work, int status) {
136             LocatingRequiredDataAsyncContext *context = nullptr;
137             napi_handle_scope scope = nullptr;
138             if (work == nullptr) {
139                 LBSLOGE(LOCATING_DATA_CALLBACK, "work is nullptr");
140                 return;
141             }
142             context = static_cast<LocatingRequiredDataAsyncContext *>(work->data);
143             if (context == nullptr || context->env == nullptr) {
144                 LBSLOGE(LOCATING_DATA_CALLBACK, "context is nullptr");
145                 delete work;
146                 return;
147             }
148             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
149             if (scope == nullptr) {
150                 LBSLOGE(LOCATING_DATA_CALLBACK, "scope is nullptr");
151                 delete context;
152                 delete work;
153                 return;
154             }
155             napi_value jsEvent = nullptr;
156             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
157                 napi_create_array_with_length(context->env, context->locatingRequiredDataList_.size(), &jsEvent),
158                 scope, context, work);
159             LocatingRequiredDataToJsObj(context->env, context->locatingRequiredDataList_, jsEvent);
160             if (context->callback[0] != nullptr) {
161                 napi_value undefine;
162                 napi_value handler = nullptr;
163                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
164                     scope, context, work);
165                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
166                     napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
167                 if (napi_call_function(context->env, nullptr, handler, 1,
168                     &jsEvent, &undefine) != napi_ok) {
169                     LBSLOGE(LOCATING_DATA_CALLBACK, "Report event failed");
170                 }
171             }
172             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
173             delete context;
174             delete work;
175     });
176 }
177 
OnLocatingDataChange(const std::vector<std::shared_ptr<LocatingRequiredData>> & data)178 void LocatingRequiredDataCallbackNapi::OnLocatingDataChange(
179     const std::vector<std::shared_ptr<LocatingRequiredData>>& data)
180 {
181     LBSLOGD(LOCATING_DATA_CALLBACK, "LocatingRequiredDataCallbackNapi::OnLocatingDataChange");
182     Send(data);
183 }
184 
DeleteHandler()185 void LocatingRequiredDataCallbackNapi::DeleteHandler()
186 {
187     std::unique_lock<std::mutex> guard(mutex_);
188     if (handlerCb_ == nullptr || env_ == nullptr) {
189         LBSLOGE(LOCATING_DATA_CALLBACK, "handler or env is nullptr.");
190         return;
191     }
192     NAPI_CALL_RETURN_VOID(env_, napi_delete_reference(env_, handlerCb_));
193     handlerCb_ = nullptr;
194 }
195 
IsSingleLocationRequest()196 bool LocatingRequiredDataCallbackNapi::IsSingleLocationRequest()
197 {
198     return (fixNumber_ == 1);
199 }
200 
CountDown()201 void LocatingRequiredDataCallbackNapi::CountDown()
202 {
203     if (IsSingleLocationRequest() && latch_ != nullptr) {
204         latch_->CountDown();
205     }
206 }
207 
Wait(int time)208 void LocatingRequiredDataCallbackNapi::Wait(int time)
209 {
210     if (IsSingleLocationRequest() && latch_ != nullptr) {
211         latch_->Wait(time);
212     }
213 }
214 
GetCount()215 int LocatingRequiredDataCallbackNapi::GetCount()
216 {
217     if (IsSingleLocationRequest() && latch_ != nullptr) {
218         return latch_->GetCount();
219     }
220     return 0;
221 }
222 
SetCount(int count)223 void LocatingRequiredDataCallbackNapi::SetCount(int count)
224 {
225     if (IsSingleLocationRequest() && latch_ != nullptr) {
226         return latch_->SetCount(count);
227     }
228 }
229 
ClearSingleResult()230 void LocatingRequiredDataCallbackNapi::ClearSingleResult()
231 {
232     std::unique_lock<std::mutex> guard(singleResultMutex_);
233     singleResult_.clear();
234 }
235 
SetSingleResult(std::vector<std::shared_ptr<LocatingRequiredData>> singleResult)236 void LocatingRequiredDataCallbackNapi::SetSingleResult(
237     std::vector<std::shared_ptr<LocatingRequiredData>> singleResult)
238 {
239     std::unique_lock<std::mutex> guard(singleResultMutex_);
240     singleResult_.assign(singleResult.begin(), singleResult.end());
241 }
242 }  // namespace Location
243 }  // namespace OHOS
244