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