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