• 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 "nmea_message_callback_napi.h"
16 
17 #include "common_utils.h"
18 #include "ipc_skeleton.h"
19 #include "location_log.h"
20 #include "napi_util.h"
21 #include "constant_definition.h"
22 #include "napi/native_api.h"
23 #include "napi/native_common.h"
24 
25 namespace OHOS {
26 namespace Location {
27 static std::mutex g_regCallbackMutex;
28 static std::vector<napi_ref> g_registerCallbacks;
NmeaMessageCallbackNapi()29 NmeaMessageCallbackNapi::NmeaMessageCallbackNapi()
30 {
31     env_ = nullptr;
32     handlerCb_ = nullptr;
33     remoteDied_ = false;
34 }
35 
~NmeaMessageCallbackNapi()36 NmeaMessageCallbackNapi::~NmeaMessageCallbackNapi()
37 {
38     LBSLOGW(NMEA_MESSAGE_CALLBACK, "~NmeaMessageCallbackNapi()");
39 }
40 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)41 int NmeaMessageCallbackNapi::OnRemoteRequest(
42     uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
43 {
44     LBSLOGD(NMEA_MESSAGE_CALLBACK, "NmeaMessageCallbackNapi::OnRemoteRequest!");
45     if (data.ReadInterfaceToken() != GetDescriptor()) {
46         LBSLOGE(NMEA_MESSAGE_CALLBACK, "invalid token.");
47         return -1;
48     }
49     if (remoteDied_) {
50         LBSLOGD(NMEA_MESSAGE_CALLBACK, "Failed to `%{public}s`,Remote service is died!", __func__);
51         return -1;
52     }
53 
54     switch (code) {
55         case RECEIVE_NMEA_MESSAGE_EVENT: {
56             int64_t timestamp = data.ReadInt64();
57             std::string msg = Str16ToStr8(data.ReadString16());
58             OnMessageChange(timestamp, msg);
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 NmeaMessageCallbackNapi::GetEnv()
70 {
71     std::unique_lock<std::mutex> guard(mutex_);
72     return env_;
73 }
74 
SetEnv(const napi_env & env)75 void NmeaMessageCallbackNapi::SetEnv(const napi_env& env)
76 {
77     std::unique_lock<std::mutex> guard(mutex_);
78     env_ = env;
79 }
80 
GetHandleCb()81 napi_ref NmeaMessageCallbackNapi::GetHandleCb()
82 {
83     std::unique_lock<std::mutex> guard(mutex_);
84     return handlerCb_;
85 }
86 
SetHandleCb(const napi_ref & handlerCb)87 void NmeaMessageCallbackNapi::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 
FindNmeaCallback(napi_ref cb)97 bool FindNmeaCallback(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 
DeleteNmeaCallback(napi_ref cb)107 void DeleteNmeaCallback(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(NMEA_MESSAGE_CALLBACK, "after DeleteNmeaCallback, callback size %{public}s",
117         std::to_string(g_registerCallbacks.size()).c_str());
118 }
119 
IsRemoteDied()120 bool NmeaMessageCallbackNapi::IsRemoteDied()
121 {
122     return remoteDied_;
123 }
124 
PackResult(const std::string msg)125 napi_value NmeaMessageCallbackNapi::PackResult(const std::string msg)
126 {
127     napi_value result;
128     NAPI_CALL(env_, napi_create_string_utf8(env_, msg.c_str(), NAPI_AUTO_LENGTH, &result));
129     return result;
130 }
131 
Send(const std::string msg)132 bool NmeaMessageCallbackNapi::Send(const std::string msg)
133 {
134     std::unique_lock<std::mutex> guard(mutex_);
135     uv_loop_s *loop = nullptr;
136     NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
137     if (loop == nullptr) {
138         LBSLOGE(NMEA_MESSAGE_CALLBACK, "loop == nullptr.");
139         return false;
140     }
141     if (handlerCb_ == nullptr) {
142         LBSLOGE(NMEA_MESSAGE_CALLBACK, "handler is nullptr.");
143         return false;
144     }
145     uv_work_t *work = new (std::nothrow) uv_work_t;
146     if (work == nullptr) {
147         LBSLOGE(NMEA_MESSAGE_CALLBACK, "work == nullptr.");
148         return false;
149     }
150     NmeaAsyncContext *context = new (std::nothrow) NmeaAsyncContext(env_);
151     if (context == nullptr) {
152         LBSLOGE(NMEA_MESSAGE_CALLBACK, "context == nullptr.");
153         delete work;
154         return false;
155     }
156     if (!InitContext(context)) {
157         LBSLOGE(NMEA_MESSAGE_CALLBACK, "InitContext fail");
158         delete work;
159         delete context;
160         return false;
161     }
162     context->msg = msg;
163     work->data = context;
164     UvQueueWork(loop, work);
165     return true;
166 }
167 
168 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)169 void NmeaMessageCallbackNapi::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
170 {
171     uv_queue_work(
172         loop,
173         work,
174         [](uv_work_t *work) {},
175         [](uv_work_t *work, int status) {
176             NmeaAsyncContext *context = nullptr;
177             napi_handle_scope scope = nullptr;
178             if (work == nullptr) {
179                 LBSLOGE(NMEA_MESSAGE_CALLBACK, "work is nullptr!");
180                 return;
181             }
182             context = static_cast<NmeaAsyncContext *>(work->data);
183             if (context == nullptr || context->env == nullptr) {
184                 LBSLOGE(NMEA_MESSAGE_CALLBACK, "context is nullptr!");
185                 delete work;
186                 return;
187             }
188             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
189             if (scope == nullptr) {
190                 LBSLOGE(NMEA_MESSAGE_CALLBACK, "scope is nullptr");
191                 delete context;
192                 delete work;
193                 return;
194             }
195             napi_value jsEvent;
196             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
197                 napi_create_string_utf8(context->env, context->msg.c_str(), NAPI_AUTO_LENGTH, &jsEvent),
198                 scope, context, work);
199             if (context->callback[0] != nullptr) {
200                 napi_value undefine;
201                 napi_value handler = nullptr;
202                 napi_status ret = napi_ok;
203                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
204                     scope, context, work);
205                 if (FindNmeaCallback(context->callback[0])) {
206                     CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
207                         napi_get_reference_value(context->env, context->callback[0], &handler),
208                         scope, context, work);
209                     ret = napi_call_function(context->env, nullptr, handler, 1, &jsEvent, &undefine);
210                 } else {
211                     LBSLOGE(NMEA_MESSAGE_CALLBACK, "no valid callback");
212                 }
213                 if (ret != napi_ok) {
214                     LBSLOGE(NMEA_MESSAGE_CALLBACK, "Report event failed");
215                 }
216             }
217             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
218             delete context;
219             delete work;
220     });
221 }
222 
OnMessageChange(int64_t timestamp,const std::string msg)223 void NmeaMessageCallbackNapi::OnMessageChange(int64_t timestamp, const std::string msg)
224 {
225     LBSLOGD(NMEA_MESSAGE_CALLBACK, "NmeaMessageCallbackNapi::OnMessageChange");
226     Send(msg);
227 }
228 
DeleteHandler()229 void NmeaMessageCallbackNapi::DeleteHandler()
230 {
231     std::unique_lock<std::mutex> guard(mutex_);
232     if (handlerCb_ == nullptr || env_ == nullptr) {
233         LBSLOGE(NMEA_MESSAGE_CALLBACK, "handler or env is nullptr.");
234         return;
235     }
236     DeleteNmeaCallback(handlerCb_);
237     NAPI_CALL_RETURN_VOID(env_, napi_delete_reference(env_, handlerCb_));
238     handlerCb_ = nullptr;
239 }
240 }  // namespace Location
241 }  // namespace OHOS
242