• 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 {
26 static std::mutex g_regCallbackMutex;
27 static std::vector<napi_ref> g_registerCallbacks;
LocatingRequiredDataCallbackNapi()28 LocatingRequiredDataCallbackNapi::LocatingRequiredDataCallbackNapi()
29 {
30     env_ = nullptr;
31     handlerCb_ = nullptr;
32     remoteDied_ = false;
33     fixNumber_ = 0;
34     InitLatch();
35 }
36 
~LocatingRequiredDataCallbackNapi()37 LocatingRequiredDataCallbackNapi::~LocatingRequiredDataCallbackNapi()
38 {
39     if (latch_ != nullptr) {
40         delete latch_;
41         latch_ = nullptr;
42     }
43     LBSLOGW(LOCATING_DATA_CALLBACK, "~LocatingRequiredDataCallbackNapi()");
44 }
45 
InitLatch()46 void LocatingRequiredDataCallbackNapi::InitLatch()
47 {
48     latch_ = new CountDownLatch();
49     latch_->SetCount(1);
50 }
51 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)52 int LocatingRequiredDataCallbackNapi::OnRemoteRequest(
53     uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
54 {
55     LBSLOGD(LOCATING_DATA_CALLBACK, "LocatingRequiredDataCallbackNapi::OnRemoteRequest!");
56     if (data.ReadInterfaceToken() != GetDescriptor()) {
57         LBSLOGE(LOCATING_DATA_CALLBACK, "invalid token.");
58         return -1;
59     }
60     if (remoteDied_) {
61         LBSLOGD(LOCATING_DATA_CALLBACK, "Failed to `%{public}s`,Remote service is died!", __func__);
62         return -1;
63     }
64 
65     switch (code) {
66         case RECEIVE_INFO_EVENT: {
67             int cnt = data.ReadInt32();
68             if (cnt >= 0 && cnt <= MAXIMUM_LOCATING_REQUIRED_DATAS) {
69                 std::vector<std::shared_ptr<LocatingRequiredData>> res;
70                 for (int i = 0; cnt > 0 && i < cnt; i++) {
71                     res.push_back(LocatingRequiredData::Unmarshalling(data));
72                 }
73                 // update wifi info
74                 if (res.size() > 0 && res[0]->GetType() == LocatingRequiredDataType::WIFI) {
75                     SetSingleResult(res);
76                 }
77                 OnLocatingDataChange(res);
78                 CountDown();
79             }
80             break;
81         }
82         default: {
83             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
84             break;
85         }
86     }
87     return 0;
88 }
89 
GetEnv()90 napi_env LocatingRequiredDataCallbackNapi::GetEnv()
91 {
92     std::unique_lock<std::mutex> guard(mutex_);
93     return env_;
94 }
95 
SetEnv(const napi_env & env)96 void LocatingRequiredDataCallbackNapi::SetEnv(const napi_env& env)
97 {
98     std::unique_lock<std::mutex> guard(mutex_);
99     env_ = env;
100 }
101 
GetHandleCb()102 napi_ref LocatingRequiredDataCallbackNapi::GetHandleCb()
103 {
104     std::unique_lock<std::mutex> guard(mutex_);
105     return handlerCb_;
106 }
107 
SetHandleCb(const napi_ref & handlerCb)108 void LocatingRequiredDataCallbackNapi::SetHandleCb(const napi_ref& handlerCb)
109 {
110     {
111         std::unique_lock<std::mutex> guard(mutex_);
112         handlerCb_ = handlerCb;
113     }
114     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
115     g_registerCallbacks.emplace_back(handlerCb);
116 }
117 
FindRequiredDataCallback(napi_ref cb)118 bool FindRequiredDataCallback(napi_ref cb)
119 {
120     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
121     auto iter = std::find(g_registerCallbacks.begin(), g_registerCallbacks.end(), cb);
122     if (iter == g_registerCallbacks.end()) {
123         return false;
124     }
125     return true;
126 }
127 
DeleteRequiredDataCallback(napi_ref cb)128 void DeleteRequiredDataCallback(napi_ref cb)
129 {
130     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
131     for (auto iter = g_registerCallbacks.begin(); iter != g_registerCallbacks.end(); iter++) {
132         if (*iter == cb) {
133             iter = g_registerCallbacks.erase(iter);
134             break;
135         }
136     }
137     LBSLOGW(LOCATING_DATA_CALLBACK, "after DeleteRequiredDataCallback, callback size %{public}s",
138         std::to_string(g_registerCallbacks.size()).c_str());
139 }
140 
IsRemoteDied()141 bool LocatingRequiredDataCallbackNapi::IsRemoteDied()
142 {
143     return remoteDied_;
144 }
145 
Send(const std::vector<std::shared_ptr<LocatingRequiredData>> & data)146 bool LocatingRequiredDataCallbackNapi::Send(const std::vector<std::shared_ptr<LocatingRequiredData>>& data)
147 {
148     if (IsSingleLocationRequest()) {
149         return false;
150     }
151     std::unique_lock<std::mutex> guard(mutex_);
152     uv_loop_s *loop = nullptr;
153     NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
154     if (loop == nullptr) {
155         LBSLOGE(LOCATING_DATA_CALLBACK, "loop == nullptr.");
156         return false;
157     }
158     if (handlerCb_ == nullptr) {
159         LBSLOGE(LOCATING_DATA_CALLBACK, "handler is nullptr.");
160         return false;
161     }
162     uv_work_t *work = new (std::nothrow) uv_work_t;
163     if (work == nullptr) {
164         LBSLOGE(LOCATING_DATA_CALLBACK, "work == nullptr.");
165         return false;
166     }
167     LocatingRequiredDataAsyncContext *context = new (std::nothrow) LocatingRequiredDataAsyncContext(env_);
168     if (context == nullptr) {
169         LBSLOGE(LOCATING_DATA_CALLBACK, "context == nullptr.");
170         delete work;
171         return false;
172     }
173     if (!InitContext(context)) {
174         LBSLOGE(LOCATING_DATA_CALLBACK, "InitContext fail");
175         delete work;
176         delete context;
177         return false;
178     }
179     context->locatingRequiredDataList_ = data;
180     work->data = context;
181     UvQueueWork(loop, work);
182     return true;
183 }
184 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)185 void LocatingRequiredDataCallbackNapi::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
186 {
187     uv_queue_work(
188         loop,
189         work,
190         [](uv_work_t *work) {},
191         [](uv_work_t *work, int status) {
192             LocatingRequiredDataAsyncContext *context = nullptr;
193             napi_handle_scope scope = nullptr;
194             if (work == nullptr) {
195                 LBSLOGE(LOCATING_DATA_CALLBACK, "work is nullptr");
196                 return;
197             }
198             context = static_cast<LocatingRequiredDataAsyncContext *>(work->data);
199             if (context == nullptr || context->env == nullptr) {
200                 LBSLOGE(LOCATING_DATA_CALLBACK, "context is nullptr");
201                 delete work;
202                 return;
203             }
204             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
205             if (scope == nullptr) {
206                 LBSLOGE(LOCATING_DATA_CALLBACK, "scope is nullptr");
207                 delete context;
208                 delete work;
209                 return;
210             }
211             napi_value jsEvent = nullptr;
212             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
213                 napi_create_array_with_length(context->env, context->locatingRequiredDataList_.size(), &jsEvent),
214                 scope, context, work);
215             LocatingRequiredDataToJsObj(context->env, context->locatingRequiredDataList_, jsEvent);
216             if (context->callback[0] != nullptr) {
217                 napi_value undefine;
218                 napi_value handler = nullptr;
219                 napi_status ret = napi_ok;
220                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
221                     scope, context, work);
222                 if (FindRequiredDataCallback(context->callback[0])) {
223                     CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
224                         napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
225                     ret = napi_call_function(context->env, nullptr, handler, 1, &jsEvent, &undefine);
226                 } else {
227                     LBSLOGE(LOCATING_DATA_CALLBACK, "no valid callback");
228                 }
229                 if (ret != napi_ok) {
230                     LBSLOGE(LOCATING_DATA_CALLBACK, "Report event failed");
231                 }
232             }
233             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
234             delete context;
235             delete work;
236     });
237 }
238 
OnLocatingDataChange(const std::vector<std::shared_ptr<LocatingRequiredData>> & data)239 void LocatingRequiredDataCallbackNapi::OnLocatingDataChange(
240     const std::vector<std::shared_ptr<LocatingRequiredData>>& data)
241 {
242     LBSLOGD(LOCATING_DATA_CALLBACK, "LocatingRequiredDataCallbackNapi::OnLocatingDataChange");
243     Send(data);
244 }
245 
DeleteHandler()246 void LocatingRequiredDataCallbackNapi::DeleteHandler()
247 {
248     std::unique_lock<std::mutex> guard(mutex_);
249     if (handlerCb_ == nullptr || env_ == nullptr) {
250         LBSLOGE(LOCATING_DATA_CALLBACK, "handler or env is nullptr.");
251         return;
252     }
253     DeleteRequiredDataCallback(handlerCb_);
254     NAPI_CALL_RETURN_VOID(env_, napi_delete_reference(env_, handlerCb_));
255     handlerCb_ = nullptr;
256 }
257 
IsSingleLocationRequest()258 bool LocatingRequiredDataCallbackNapi::IsSingleLocationRequest()
259 {
260     return (fixNumber_ == 1);
261 }
262 
CountDown()263 void LocatingRequiredDataCallbackNapi::CountDown()
264 {
265     if (IsSingleLocationRequest() && latch_ != nullptr) {
266         latch_->CountDown();
267     }
268 }
269 
Wait(int time)270 void LocatingRequiredDataCallbackNapi::Wait(int time)
271 {
272     if (IsSingleLocationRequest() && latch_ != nullptr) {
273         latch_->Wait(time);
274     }
275 }
276 
GetCount()277 int LocatingRequiredDataCallbackNapi::GetCount()
278 {
279     if (IsSingleLocationRequest() && latch_ != nullptr) {
280         return latch_->GetCount();
281     }
282     return 0;
283 }
284 
SetCount(int count)285 void LocatingRequiredDataCallbackNapi::SetCount(int count)
286 {
287     if (IsSingleLocationRequest() && latch_ != nullptr) {
288         return latch_->SetCount(count);
289     }
290 }
291 
ClearSingleResult()292 void LocatingRequiredDataCallbackNapi::ClearSingleResult()
293 {
294     std::unique_lock<std::mutex> guard(singleResultMutex_);
295     singleResult_.clear();
296 }
297 
SetSingleResult(std::vector<std::shared_ptr<LocatingRequiredData>> singleResult)298 void LocatingRequiredDataCallbackNapi::SetSingleResult(
299     std::vector<std::shared_ptr<LocatingRequiredData>> singleResult)
300 {
301     std::unique_lock<std::mutex> guard(singleResultMutex_);
302     singleResult_.assign(singleResult.begin(), singleResult.end());
303 }
304 }  // namespace Location
305 }  // namespace OHOS
306