• 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 "gnss_status_callback_napi.h"
16 
17 #include "napi/native_common.h"
18 
19 #include "common_utils.h"
20 #include "ipc_skeleton.h"
21 #include "location_log.h"
22 #include "napi_util.h"
23 #include "common_utils.h"
24 #include "constant_definition.h"
25 
26 namespace OHOS {
27 namespace Location {
28 static std::mutex g_regCallbackMutex;
29 static std::vector<napi_ref> g_registerCallbacks;
GnssStatusCallbackNapi()30 GnssStatusCallbackNapi::GnssStatusCallbackNapi()
31 {
32     env_ = nullptr;
33     handlerCb_ = nullptr;
34     remoteDied_ = false;
35 }
36 
~GnssStatusCallbackNapi()37 GnssStatusCallbackNapi::~GnssStatusCallbackNapi()
38 {
39     LBSLOGW(GNSS_STATUS_CALLBACK, "~GnssStatusCallbackNapi()");
40 }
41 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)42 int GnssStatusCallbackNapi::OnRemoteRequest(
43     uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
44 {
45     LBSLOGD(GNSS_STATUS_CALLBACK, "GnssStatusCallbackNapi::OnRemoteRequest!");
46     if (data.ReadInterfaceToken() != GetDescriptor()) {
47         LBSLOGE(GNSS_STATUS_CALLBACK, "invalid token.");
48         return -1;
49     }
50     if (remoteDied_) {
51         LBSLOGD(GNSS_STATUS_CALLBACK, "Failed to `%{public}s`,Remote service is died!", __func__);
52         return -1;
53     }
54 
55     switch (code) {
56         case RECEIVE_STATUS_INFO_EVENT: {
57             std::unique_ptr<SatelliteStatus> statusInfo = SatelliteStatus::Unmarshalling(data);
58             Send(statusInfo);
59             break;
60         }
61         default: {
62             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
63             break;
64         }
65     }
66     return 0;
67 }
68 
GetEnv()69 napi_env GnssStatusCallbackNapi::GetEnv()
70 {
71     std::unique_lock<std::mutex> guard(mutex_);
72     return env_;
73 }
74 
SetEnv(const napi_env & env)75 void GnssStatusCallbackNapi::SetEnv(const napi_env& env)
76 {
77     std::unique_lock<std::mutex> guard(mutex_);
78     env_ = env;
79 }
80 
GetHandleCb()81 napi_ref GnssStatusCallbackNapi::GetHandleCb()
82 {
83     std::unique_lock<std::mutex> guard(mutex_);
84     return handlerCb_;
85 }
86 
SetHandleCb(const napi_ref & handlerCb)87 void GnssStatusCallbackNapi::SetHandleCb(const napi_ref& handlerCb)
88 {
89     {
90         std::unique_lock<std::mutex> guard(mutex_);
91         handlerCb_ = handlerCb;
92     }
93     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
94     g_registerCallbacks.emplace_back(handlerCb);
95 }
96 
FindGnssStatusCallback(napi_ref cb)97 bool FindGnssStatusCallback(napi_ref cb)
98 {
99     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
100     auto iter = std::find(g_registerCallbacks.begin(), g_registerCallbacks.end(), cb);
101     if (iter == g_registerCallbacks.end()) {
102         return false;
103     }
104     return true;
105 }
106 
DeleteGnssStatusCallback(napi_ref cb)107 void DeleteGnssStatusCallback(napi_ref cb)
108 {
109     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
110     for (auto iter = g_registerCallbacks.begin(); iter != g_registerCallbacks.end(); iter++) {
111         if (*iter == cb) {
112             iter = g_registerCallbacks.erase(iter);
113             break;
114         }
115     }
116     LBSLOGW(GNSS_STATUS_CALLBACK, "after DeleteGnssStatusCallback, callback size %{public}s",
117         std::to_string(g_registerCallbacks.size()).c_str());
118 }
119 
IsRemoteDied()120 bool GnssStatusCallbackNapi::IsRemoteDied()
121 {
122     return remoteDied_;
123 }
124 
Send(std::unique_ptr<SatelliteStatus> & statusInfo)125 bool GnssStatusCallbackNapi::Send(std::unique_ptr<SatelliteStatus>& statusInfo)
126 {
127     std::unique_lock<std::mutex> guard(mutex_);
128     uv_loop_s *loop = nullptr;
129     NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
130     if (loop == nullptr) {
131         LBSLOGE(GNSS_STATUS_CALLBACK, "loop == nullptr.");
132         return false;
133     }
134     if (handlerCb_ == nullptr) {
135         LBSLOGE(GNSS_STATUS_CALLBACK, "handler is nullptr.");
136         return false;
137     }
138     uv_work_t *work = new (std::nothrow) uv_work_t;
139     if (work == nullptr) {
140         LBSLOGE(GNSS_STATUS_CALLBACK, "work == nullptr.");
141         return false;
142     }
143     GnssStatusAsyncContext *context = new (std::nothrow) GnssStatusAsyncContext(env_);
144     if (context == nullptr) {
145         LBSLOGE(GNSS_STATUS_CALLBACK, "context == nullptr.");
146         delete work;
147         return false;
148     }
149     if (!InitContext(context)) {
150         LBSLOGE(GNSS_STATUS_CALLBACK, "InitContext fail");
151         delete work;
152         delete context;
153         return false;
154     }
155     context->statusInfo = std::move(statusInfo);
156     work->data = context;
157     UvQueueWork(loop, work);
158     return true;
159 }
160 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)161 void GnssStatusCallbackNapi::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
162 {
163     uv_queue_work(
164         loop,
165         work,
166         [](uv_work_t *work) {},
167         [](uv_work_t *work, int status) {
168             GnssStatusAsyncContext *context = nullptr;
169             napi_handle_scope scope = nullptr;
170             if (work == nullptr) {
171                 LBSLOGE(LOCATOR_CALLBACK, "work is nullptr!");
172                 return;
173             }
174             context = static_cast<GnssStatusAsyncContext *>(work->data);
175             if (context == nullptr || context->env == nullptr) {
176                 LBSLOGE(LOCATOR_CALLBACK, "context is nullptr!");
177                 delete work;
178                 return;
179             }
180             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
181             if (scope == nullptr) {
182                 LBSLOGE(GNSS_STATUS_CALLBACK, "scope is nullptr");
183                 delete context;
184                 delete work;
185                 return;
186             }
187             napi_value jsEvent = nullptr;
188             if (context->statusInfo != nullptr) {
189                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_create_object(context->env, &jsEvent),
190                     scope, context, work);
191                 SatelliteStatusToJs(context->env, context->statusInfo, jsEvent);
192             }
193             if (context->callback[0] != nullptr) {
194                 napi_value undefine;
195                 napi_value handler = nullptr;
196                 napi_status ret = napi_ok;
197                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
198                     scope, context, work);
199                 if (FindGnssStatusCallback(context->callback[0])) {
200                     CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
201                         napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
202                     ret = napi_call_function(context->env, nullptr, handler, 1, &jsEvent, &undefine);
203                 } else {
204                     LBSLOGE(GNSS_STATUS_CALLBACK, "no valid callback");
205                 }
206                 if (ret != napi_ok) {
207                     LBSLOGE(GNSS_STATUS_CALLBACK, "Report event failed");
208                 }
209             }
210             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
211             delete context;
212             delete work;
213     });
214 }
215 
OnStatusChange(const std::unique_ptr<SatelliteStatus> & statusInfo)216 void GnssStatusCallbackNapi::OnStatusChange(const std::unique_ptr<SatelliteStatus>& statusInfo)
217 {
218     LBSLOGD(GNSS_STATUS_CALLBACK, "GnssStatusCallbackNapi::OnStatusChange");
219 }
220 
DeleteHandler()221 void GnssStatusCallbackNapi::DeleteHandler()
222 {
223     std::unique_lock<std::mutex> guard(mutex_);
224     if (handlerCb_ == nullptr || env_ == nullptr) {
225         LBSLOGE(GNSS_STATUS_CALLBACK, "handler or env is nullptr.");
226         return;
227     }
228     DeleteGnssStatusCallback(handlerCb_);
229     NAPI_CALL_RETURN_VOID(env_, napi_delete_reference(env_, handlerCb_));
230     handlerCb_ = nullptr;
231 }
232 }  // namespace Location
233 }  // namespace OHOS
234