• 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 "location_gnss_geofence_callback_napi.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 #include "geofence_napi.h"
24 #include "location_async_context.h"
25 #include "geofence_async_context.h"
26 
27 namespace OHOS {
28 namespace Location {
LocationGnssGeofenceCallbackNapi()29 LocationGnssGeofenceCallbackNapi::LocationGnssGeofenceCallbackNapi()
30 {
31     env_ = nullptr;
32     handlerCb_ = nullptr;
33     remoteDied_ = false;
34     fenceId_ = -1;
35     type_ = GNSS_GEOFENCE_OPT_TYPE_ADD;
36     result_ = GNSS_GEOFENCE_OPERATION_SUCCESS;
37     InitLatch();
38 }
39 
~LocationGnssGeofenceCallbackNapi()40 LocationGnssGeofenceCallbackNapi::~LocationGnssGeofenceCallbackNapi()
41 {
42     if (latch_ != nullptr) {
43         delete latch_;
44         latch_ = nullptr;
45     }
46 }
47 
InitLatch()48 void LocationGnssGeofenceCallbackNapi::InitLatch()
49 {
50     latch_ = new CountDownLatch();
51     latch_->SetCount(1);
52 }
53 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)54 int LocationGnssGeofenceCallbackNapi::OnRemoteRequest(
55     uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
56 {
57     LBSLOGD(LOCATION_GNSS_GEOFENCE_CALLBACK, "OnRemoteRequest enter");
58     if (data.ReadInterfaceToken() != GetDescriptor()) {
59         LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "invalid token.");
60         return -1;
61     }
62     if (remoteDied_) {
63         LBSLOGD(LOCATION_GNSS_GEOFENCE_CALLBACK, "Failed to `%{public}s`,Remote service is died!", __func__);
64         return -1;
65     }
66     switch (code) {
67         case RECEIVE_TRANSITION_STATUS_EVENT: {
68             GeofenceTransition transition;
69             transition.fenceId = data.ReadInt32();
70             transition.event =
71                 static_cast<GeofenceTransitionEvent>(data.ReadInt32());
72             OnTransitionStatusChange(transition);
73             break;
74         }
75         case REPORT_OPERATION_RESULT_EVENT: {
76             int fenceId = data.ReadInt32();
77             int type = data.ReadInt32();
78             int result = data.ReadInt32();
79             OnReportOperationResult(fenceId, type, result);
80             CountDown();
81             break;
82         }
83         default: {
84             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
85             break;
86         }
87     }
88     return 0;
89 }
90 
OnTransitionStatusChange(GeofenceTransition transition)91 void LocationGnssGeofenceCallbackNapi::OnTransitionStatusChange(
92     GeofenceTransition transition)
93 {
94     std::unique_lock<std::mutex> guard(mutex_);
95     uv_loop_s *loop = nullptr;
96     NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop));
97     if (loop == nullptr) {
98         LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "loop == nullptr.");
99         return;
100     }
101     if (handlerCb_ == nullptr) {
102         LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "handler is nullptr.");
103         return;
104     }
105     uv_work_t *work = new (std::nothrow) uv_work_t;
106     if (work == nullptr) {
107         LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "work == nullptr.");
108         return;
109     }
110     GnssGeofenceAsyncContext *context = new (std::nothrow) GnssGeofenceAsyncContext(env_);
111     if (context == nullptr) {
112         LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "context == nullptr.");
113         delete work;
114         return;
115     }
116     if (!InitContext(context)) {
117         LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "InitContext fail");
118         return;
119     }
120     context->transition_ = transition;
121     work->data = context;
122     UvQueueWork(loop, work);
123 }
124 
OnReportOperationResult(int fenceId,int type,int result)125 void LocationGnssGeofenceCallbackNapi::OnReportOperationResult(int fenceId, int type, int result)
126 {
127     int addValue = static_cast<int>(GnssGeofenceOperateType::GNSS_GEOFENCE_OPT_TYPE_ADD);
128     if ((type != addValue && fenceId == GetFenceId()) ||
129         (type == addValue)) {
130         GnssGeofenceOperateResult optResult = static_cast<GnssGeofenceOperateResult>(result);
131         GnssGeofenceOperateType optType = static_cast<GnssGeofenceOperateType>(type);
132         if (result == GnssGeofenceOperateResult::GNSS_GEOFENCE_OPERATION_SUCCESS &&
133             optType == GnssGeofenceOperateType::GNSS_GEOFENCE_OPT_TYPE_ADD) {
134             SetFenceId(fenceId);
135         }
136         SetGeofenceOperationType(optType);
137         SetGeofenceOperationResult(optResult);
138     }
139 }
140 
IsRemoteDied()141 bool LocationGnssGeofenceCallbackNapi::IsRemoteDied()
142 {
143     return remoteDied_;
144 }
145 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)146 void LocationGnssGeofenceCallbackNapi::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
147 {
148     uv_queue_work(
149         loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
150             GnssGeofenceAsyncContext *context = nullptr;
151             napi_handle_scope scope = nullptr;
152             if (work == nullptr) {
153                 LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "work is nullptr");
154                 return;
155             }
156             context = static_cast<GnssGeofenceAsyncContext *>(work->data);
157             if (context == nullptr || context->env == nullptr) {
158                 LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "context is nullptr");
159                 delete work;
160                 return;
161             }
162             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
163             if (scope == nullptr) {
164                 LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "scope is nullptr");
165                 delete context;
166                 delete work;
167                 return;
168             }
169             napi_value jsEvent[PARAM2];
170             CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_create_object(context->env, &jsEvent[PARAM1]),
171                 scope, context, work);
172             CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &jsEvent[PARAM0]),
173                 scope, context, work);
174             GeofenceTransitionToJs(context->env, context->transition_, jsEvent[PARAM1]);
175             if (context->callback[SUCCESS_CALLBACK] != nullptr) {
176                 napi_value undefine;
177                 napi_value handler = nullptr;
178                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
179                     scope, context, work);
180                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
181                     napi_get_reference_value(context->env, context->callback[SUCCESS_CALLBACK], &handler),
182                     scope, context, work);
183                 if (napi_call_function(context->env, nullptr, handler, RESULT_SIZE, jsEvent, &undefine) != napi_ok) {
184                     LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "Report event failed");
185                 }
186             }
187             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
188             delete context;
189             delete work;
190     });
191 }
192 
DeleteHandler()193 void LocationGnssGeofenceCallbackNapi::DeleteHandler()
194 {
195     std::unique_lock<std::mutex> guard(mutex_);
196     if (handlerCb_ == nullptr || env_ == nullptr) {
197         LBSLOGE(LOCATION_GNSS_GEOFENCE_CALLBACK, "handler or env is nullptr.");
198         return;
199     }
200     NAPI_CALL_RETURN_VOID(env_, napi_delete_reference(env_, handlerCb_));
201     handlerCb_ = nullptr;
202 }
203 
CountDown()204 void LocationGnssGeofenceCallbackNapi::CountDown()
205 {
206     if (latch_ != nullptr) {
207         latch_->CountDown();
208     }
209 }
210 
Wait(int time)211 void LocationGnssGeofenceCallbackNapi::Wait(int time)
212 {
213     if (latch_ != nullptr) {
214         latch_->Wait(time);
215     }
216 }
217 
GetCount()218 int LocationGnssGeofenceCallbackNapi::GetCount()
219 {
220     if (latch_ != nullptr) {
221         return latch_->GetCount();
222     }
223     return 0;
224 }
225 
SetCount(int count)226 void LocationGnssGeofenceCallbackNapi::SetCount(int count)
227 {
228     if (latch_ != nullptr) {
229         return latch_->SetCount(count);
230     }
231 }
232 
ClearFenceId()233 void LocationGnssGeofenceCallbackNapi::ClearFenceId()
234 {
235     std::unique_lock<std::mutex> guard(operationResultMutex_);
236     fenceId_ = -1;
237 }
238 
GetFenceId()239 int LocationGnssGeofenceCallbackNapi::GetFenceId()
240 {
241     std::unique_lock<std::mutex> guard(operationResultMutex_);
242     return fenceId_;
243 }
244 
SetFenceId(int fenceId)245 void LocationGnssGeofenceCallbackNapi::SetFenceId(int fenceId)
246 {
247     std::unique_lock<std::mutex> guard(operationResultMutex_);
248     fenceId_ = fenceId;
249 }
250 
GetGeofenceOperationType()251 GnssGeofenceOperateType LocationGnssGeofenceCallbackNapi::GetGeofenceOperationType()
252 {
253     std::unique_lock<std::mutex> guard(operationResultMutex_);
254     return type_;
255 }
256 
SetGeofenceOperationType(GnssGeofenceOperateType type)257 void LocationGnssGeofenceCallbackNapi::SetGeofenceOperationType(GnssGeofenceOperateType type)
258 {
259     std::unique_lock<std::mutex> guard(operationResultMutex_);
260     type_ = type;
261 }
262 
GetGeofenceOperationResult()263 GnssGeofenceOperateResult LocationGnssGeofenceCallbackNapi::GetGeofenceOperationResult()
264 {
265     std::unique_lock<std::mutex> guard(operationResultMutex_);
266     return result_;
267 }
268 
SetGeofenceOperationResult(GnssGeofenceOperateResult result)269 void LocationGnssGeofenceCallbackNapi::SetGeofenceOperationResult(GnssGeofenceOperateResult result)
270 {
271     std::unique_lock<std::mutex> guard(operationResultMutex_);
272     result_ = result;
273 }
274 
DealGeofenceOperationResult()275 LocationErrCode LocationGnssGeofenceCallbackNapi::DealGeofenceOperationResult()
276 {
277     std::unique_lock<std::mutex> guard(operationResultMutex_);
278     LocationErrCode errCode = ERRCODE_SUCCESS;
279     GnssGeofenceOperateResult result = result_;
280     switch (result) {
281         case GnssGeofenceOperateResult::GNSS_GEOFENCE_OPERATION_SUCCESS:
282             errCode = ERRCODE_SUCCESS;
283             break;
284         case GnssGeofenceOperateResult::GNSS_GEOFENCE_OPERATION_ERROR_UNKNOWN:
285             errCode = ERRCODE_SERVICE_UNAVAILABLE;
286             break;
287         case GnssGeofenceOperateResult::GNSS_GEOFENCE_OPERATION_ERROR_TOO_MANY_GEOFENCES:
288             errCode = ERRCODE_GEOFENCE_EXCEED_MAXIMUM;
289             break;
290         case GnssGeofenceOperateResult::GNSS_GEOFENCE_OPERATION_ERROR_GEOFENCE_ID_EXISTS:
291             errCode = ERRCODE_SERVICE_UNAVAILABLE;
292             break;
293         case GnssGeofenceOperateResult::GNSS_GEOFENCE_OPERATION_ERROR_PARAMS_INVALID:
294             errCode = ERRCODE_SERVICE_UNAVAILABLE;
295             break;
296         case GnssGeofenceOperateResult::GNSS_GEOFENCE_OPERATION_ERROR_GEOFENCE_ID_UNKNOWN:
297             errCode = ERRCODE_GEOFENCE_INCORRECT_ID;
298             break;
299         default:
300             break;
301     }
302     return errCode;
303 }
304 }  // namespace Location
305 }  // namespace OHOS
306