1 /*
2 * Copyright (C) 2023 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_host.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 {
LocatingRequiredDataCallbackHost()26 LocatingRequiredDataCallbackHost::LocatingRequiredDataCallbackHost()
27 {
28 env_ = nullptr;
29 handlerCb_ = nullptr;
30 remoteDied_ = false;
31 fixNumber_ = 0;
32 InitLatch();
33 }
34
~LocatingRequiredDataCallbackHost()35 LocatingRequiredDataCallbackHost::~LocatingRequiredDataCallbackHost()
36 {
37 if (latch_ != nullptr) {
38 delete latch_;
39 latch_ = nullptr;
40 }
41 }
42
InitLatch()43 void LocatingRequiredDataCallbackHost::InitLatch()
44 {
45 latch_ = new CountDownLatch();
46 latch_->SetCount(1);
47 }
48
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)49 int LocatingRequiredDataCallbackHost::OnRemoteRequest(
50 uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
51 {
52 LBSLOGD(LOCATING_DATA_CALLBACK, "LocatingRequiredDataCallbackHost::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 LocatingRequiredDataCallbackHost::IsRemoteDied()
88 {
89 return remoteDied_;
90 }
91
Send(const std::vector<std::shared_ptr<LocatingRequiredData>> & data)92 bool LocatingRequiredDataCallbackHost::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 uv_work_t *work = new (std::nothrow) uv_work_t;
105 if (work == nullptr) {
106 LBSLOGE(LOCATING_DATA_CALLBACK, "work == nullptr.");
107 return false;
108 }
109 LocatingRequiredDataAsyncContext *context = new (std::nothrow) LocatingRequiredDataAsyncContext(env_);
110 if (context == nullptr) {
111 LBSLOGE(LOCATING_DATA_CALLBACK, "context == nullptr.");
112 delete work;
113 return false;
114 }
115 context->env = env_;
116 context->callback[SUCCESS_CALLBACK] = handlerCb_;
117 context->locatingRequiredDataList_ = data;
118 work->data = context;
119 UvQueueWork(loop, work);
120 return true;
121 }
122
UvQueueWork(uv_loop_s * loop,uv_work_t * work)123 void LocatingRequiredDataCallbackHost::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
124 {
125 uv_queue_work(
126 loop,
127 work,
128 [](uv_work_t *work) {},
129 [](uv_work_t *work, int status) {
130 LocatingRequiredDataAsyncContext *context = nullptr;
131 napi_handle_scope scope = nullptr;
132 if (work == nullptr) {
133 LBSLOGE(LOCATING_DATA_CALLBACK, "work is nullptr");
134 return;
135 }
136 context = static_cast<LocatingRequiredDataAsyncContext *>(work->data);
137 if (context == nullptr || context->env == nullptr) {
138 LBSLOGE(LOCATING_DATA_CALLBACK, "context is nullptr");
139 delete work;
140 return;
141 }
142 NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
143 if (scope == nullptr) {
144 LBSLOGE(LOCATING_DATA_CALLBACK, "scope is nullptr");
145 delete context;
146 delete work;
147 return;
148 }
149 napi_value jsEvent = nullptr;
150 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
151 napi_create_array_with_length(context->env, context->locatingRequiredDataList_.size(), &jsEvent),
152 scope, context, work);
153 LocatingRequiredDataToJsObj(context->env, context->locatingRequiredDataList_, jsEvent);
154 if (context->callback[0] != nullptr) {
155 napi_value undefine;
156 napi_value handler = nullptr;
157 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
158 scope, context, work);
159 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
160 napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
161 if (napi_call_function(context->env, nullptr, handler, 1,
162 &jsEvent, &undefine) != napi_ok) {
163 LBSLOGE(LOCATING_DATA_CALLBACK, "Report event failed");
164 }
165 }
166 NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
167 delete context;
168 delete work;
169 });
170 }
171
OnLocatingDataChange(const std::vector<std::shared_ptr<LocatingRequiredData>> & data)172 void LocatingRequiredDataCallbackHost::OnLocatingDataChange(
173 const std::vector<std::shared_ptr<LocatingRequiredData>>& data)
174 {
175 LBSLOGD(LOCATING_DATA_CALLBACK, "LocatingRequiredDataCallbackHost::OnLocatingDataChange");
176 Send(data);
177 }
178
DeleteHandler()179 void LocatingRequiredDataCallbackHost::DeleteHandler()
180 {
181 std::unique_lock<std::mutex> guard(mutex_);
182 if (handlerCb_ == nullptr || env_ == nullptr) {
183 LBSLOGE(LOCATING_DATA_CALLBACK, "handler or env is nullptr.");
184 return;
185 }
186 auto context = new (std::nothrow) AsyncContext(env_);
187 if (context == nullptr) {
188 LBSLOGE(LOCATING_DATA_CALLBACK, "context == nullptr.");
189 return;
190 }
191 context->env = env_;
192 context->callback[SUCCESS_CALLBACK] = handlerCb_;
193 DeleteQueueWork(context);
194 handlerCb_ = nullptr;
195 }
196
IsSingleLocationRequest()197 bool LocatingRequiredDataCallbackHost::IsSingleLocationRequest()
198 {
199 return (fixNumber_ == 1);
200 }
201
CountDown()202 void LocatingRequiredDataCallbackHost::CountDown()
203 {
204 if (IsSingleLocationRequest() && latch_ != nullptr) {
205 latch_->CountDown();
206 }
207 }
208
Wait(int time)209 void LocatingRequiredDataCallbackHost::Wait(int time)
210 {
211 if (IsSingleLocationRequest() && latch_ != nullptr) {
212 latch_->Wait(time);
213 }
214 }
215
GetCount()216 int LocatingRequiredDataCallbackHost::GetCount()
217 {
218 if (IsSingleLocationRequest() && latch_ != nullptr) {
219 return latch_->GetCount();
220 }
221 return 0;
222 }
223
SetCount(int count)224 void LocatingRequiredDataCallbackHost::SetCount(int count)
225 {
226 if (IsSingleLocationRequest() && latch_ != nullptr) {
227 return latch_->SetCount(count);
228 }
229 }
230
ClearSingleResult()231 void LocatingRequiredDataCallbackHost::ClearSingleResult()
232 {
233 std::unique_lock<std::mutex> guard(singleResultMutex_);
234 singleResult_.clear();
235 }
236
SetSingleResult(std::vector<std::shared_ptr<LocatingRequiredData>> singleResult)237 void LocatingRequiredDataCallbackHost::SetSingleResult(
238 std::vector<std::shared_ptr<LocatingRequiredData>> singleResult)
239 {
240 std::unique_lock<std::mutex> guard(singleResultMutex_);
241 singleResult_.assign(singleResult.begin(), singleResult.end());
242 }
243 } // namespace Location
244 } // namespace OHOS
245