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