• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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_host.h"
16 
17 #include "common_utils.h"
18 #include "ipc_skeleton.h"
19 #include "location_log.h"
20 #include "location_napi_adapter.h"
21 #include "napi/native_api.h"
22 #include "napi/native_common.h"
23 
24 namespace OHOS {
25 namespace Location {
NmeaMessageCallbackHost()26 NmeaMessageCallbackHost::NmeaMessageCallbackHost()
27 {
28     env_ = nullptr;
29     handlerCb_ = nullptr;
30     remoteDied_ = false;
31 }
32 
~NmeaMessageCallbackHost()33 NmeaMessageCallbackHost::~NmeaMessageCallbackHost()
34 {
35 }
36 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)37 int NmeaMessageCallbackHost::OnRemoteRequest(
38     uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
39 {
40     LBSLOGD(NMEA_MESSAGE_CALLBACK, "NmeaMessageCallbackHost::OnRemoteRequest!");
41     if (data.ReadInterfaceToken() != GetDescriptor()) {
42         LBSLOGE(NMEA_MESSAGE_CALLBACK, "invalid token.");
43         return -1;
44     }
45     if (remoteDied_) {
46         LBSLOGD(NMEA_MESSAGE_CALLBACK, "Failed to `%{public}s`,Remote service is died!", __func__);
47         return -1;
48     }
49 
50     switch (code) {
51         case RECEIVE_NMEA_MESSAGE_EVENT: {
52             int64_t timestamp = data.ReadInt64();
53             std::string msg = Str16ToStr8(data.ReadString16());
54             OnMessageChange(timestamp, msg);
55             break;
56         }
57         default: {
58             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
59             break;
60         }
61     }
62     return 0;
63 }
64 
IsRemoteDied()65 bool NmeaMessageCallbackHost::IsRemoteDied()
66 {
67     return remoteDied_;
68 }
69 
PackResult(const std::string msg)70 napi_value NmeaMessageCallbackHost::PackResult(const std::string msg)
71 {
72     napi_value result;
73     NAPI_CALL(env_, napi_create_string_utf8(env_, msg.c_str(), NAPI_AUTO_LENGTH, &result));
74     return result;
75 }
76 
Send(const std::string msg)77 bool NmeaMessageCallbackHost::Send(const std::string msg)
78 {
79     std::shared_lock<std::shared_mutex> guard(mutex_);
80 
81     uv_loop_s *loop = nullptr;
82     NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
83     if (loop == nullptr) {
84         LBSLOGE(NMEA_MESSAGE_CALLBACK, "loop == nullptr.");
85         return false;
86     }
87     uv_work_t *work = new (std::nothrow) uv_work_t;
88     if (work == nullptr) {
89         LBSLOGE(NMEA_MESSAGE_CALLBACK, "work == nullptr.");
90         return false;
91     }
92     NmeaAsyncContext *context = new (std::nothrow) NmeaAsyncContext(env_);
93     if (context == nullptr) {
94         LBSLOGE(NMEA_MESSAGE_CALLBACK, "context == nullptr.");
95         return false;
96     }
97     context->env = env_;
98     context->callback[SUCCESS_CALLBACK] = handlerCb_;
99     context->msg = msg;
100     work->data = context;
101     UvQueueWork(loop, work);
102     return true;
103 }
104 
105 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)106 void NmeaMessageCallbackHost::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
107 {
108     uv_queue_work(
109         loop,
110         work,
111         [](uv_work_t *work) {},
112         [](uv_work_t *work, int status) {
113             NmeaAsyncContext *context = nullptr;
114             napi_handle_scope scope = nullptr;
115             if (work == nullptr) {
116                 LBSLOGE(LOCATOR_CALLBACK, "work is nullptr!");
117                 return;
118             }
119             context = static_cast<NmeaAsyncContext *>(work->data);
120             if (context == nullptr || context->env == nullptr) {
121                 LBSLOGE(LOCATOR_CALLBACK, "context is nullptr!");
122                 delete work;
123                 return;
124             }
125             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
126             if (scope == nullptr) {
127                 LBSLOGE(NMEA_MESSAGE_CALLBACK, "scope is nullptr");
128                 delete context;
129                 delete work;
130                 return;
131             }
132             napi_value jsEvent;
133             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
134                 napi_create_string_utf8(context->env, context->msg.c_str(), NAPI_AUTO_LENGTH, &jsEvent),
135                 scope, context, work);
136             if (context->callback[0] != nullptr) {
137                 napi_value undefine;
138                 napi_value handler = nullptr;
139                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
140                     scope, context, work);
141                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
142                     napi_get_reference_value(context->env, context->callback[0], &handler),
143                     scope, context, work);
144                 if (napi_call_function(context->env, nullptr, handler, 1,
145                     &jsEvent, &undefine) != napi_ok) {
146                     LBSLOGE(NMEA_MESSAGE_CALLBACK, "Report event failed");
147                 }
148             }
149             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
150             delete context;
151             delete work;
152     });
153 }
154 
OnMessageChange(int64_t timestamp,const std::string msg)155 void NmeaMessageCallbackHost::OnMessageChange(int64_t timestamp, const std::string msg)
156 {
157     LBSLOGD(NMEA_MESSAGE_CALLBACK, "NmeaMessageCallbackHost::OnMessageChange");
158     Send(msg);
159 }
160 
DeleteHandler()161 void NmeaMessageCallbackHost::DeleteHandler()
162 {
163     std::shared_lock<std::shared_mutex> guard(mutex_);
164     if (handlerCb_ == nullptr || env_ == nullptr) {
165         LBSLOGE(NMEA_MESSAGE_CALLBACK, "handler or env is nullptr.");
166         return;
167     }
168     auto context = new (std::nothrow) AsyncContext(env_);
169     if (context == nullptr) {
170         LBSLOGE(NMEA_MESSAGE_CALLBACK, "context == nullptr.");
171         return;
172     }
173     context->env = env_;
174     context->callback[SUCCESS_CALLBACK] = handlerCb_;
175     DeleteQueueWork(context);
176     handlerCb_ = nullptr;
177 }
178 }  // namespace Location
179 }  // namespace OHOS
180