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 "cached_locations_callback_host.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 {
CachedLocationsCallbackHost()26 CachedLocationsCallbackHost::CachedLocationsCallbackHost()
27 {
28 env_ = nullptr;
29 handlerCb_ = nullptr;
30 remoteDied_ = false;
31 }
32
~CachedLocationsCallbackHost()33 CachedLocationsCallbackHost::~CachedLocationsCallbackHost()
34 {
35 }
36
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)37 int CachedLocationsCallbackHost::OnRemoteRequest(
38 uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
39 {
40 LBSLOGD(CACHED_LOCATIONS_CALLBACK, "CachedLocationsCallbackHost::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::shared_ptr<Location>> locations(size);
55 for (int i = 0; i < size; i++) {
56 locations.push_back(Location::UnmarshallingShared(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 CachedLocationsCallbackHost::IsRemoteDied()
71 {
72 return remoteDied_;
73 }
74
Send(std::vector<std::shared_ptr<Location>> & locations)75 bool CachedLocationsCallbackHost::Send(std::vector<std::shared_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 uv_work_t *work = new (std::nothrow) uv_work_t;
85 if (work == nullptr) {
86 LBSLOGE(CACHED_LOCATIONS_CALLBACK, "work == nullptr.");
87 return false;
88 }
89 CachedLocationAsyncContext *context = new (std::nothrow) CachedLocationAsyncContext(env_);
90 if (context == nullptr) {
91 LBSLOGE(CACHED_LOCATIONS_CALLBACK, "context == nullptr.");
92 return false;
93 }
94 context->env = env_;
95 context->callback[SUCCESS_CALLBACK] = handlerCb_;
96 context->locationList = locations;
97 work->data = context;
98 UvQueueWork(loop, work);
99 return true;
100 }
101
UvQueueWork(uv_loop_s * loop,uv_work_t * work)102 void CachedLocationsCallbackHost::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
103 {
104 uv_queue_work(
105 loop,
106 work,
107 [](uv_work_t *work) {},
108 [](uv_work_t *work, int status) {
109 CachedLocationAsyncContext *context = nullptr;
110 napi_handle_scope scope = nullptr;
111 if (work == nullptr) {
112 LBSLOGE(CACHED_LOCATIONS_CALLBACK, "work is nullptr");
113 return;
114 }
115 context = static_cast<CachedLocationAsyncContext *>(work->data);
116 if (context == nullptr || context->env == nullptr) {
117 LBSLOGE(CACHED_LOCATIONS_CALLBACK, "context is nullptr");
118 delete work;
119 return;
120 }
121 NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
122 if (scope == nullptr) {
123 LBSLOGE(CACHED_LOCATIONS_CALLBACK, "scope is nullptr");
124 delete context;
125 delete work;
126 return;
127 }
128 napi_value jsEvent = nullptr;
129 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_create_object(context->env, &jsEvent),
130 scope, context, work);
131 LocationsToJs(context->env, context->locationList, jsEvent);
132 if (context->callback[0] != nullptr) {
133 napi_value undefine;
134 napi_value handler = nullptr;
135 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
136 scope, context, work);
137 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
138 napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
139 if (napi_call_function(context->env, nullptr, handler, 1,
140 &jsEvent, &undefine) != napi_ok) {
141 LBSLOGE(CACHED_LOCATIONS_CALLBACK, "Report event failed");
142 }
143 }
144 NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
145 delete context;
146 delete work;
147 });
148 }
149
OnCacheLocationsReport(const std::vector<std::unique_ptr<Location>> & locations)150 void CachedLocationsCallbackHost::OnCacheLocationsReport(const std::vector<std::unique_ptr<Location>>& locations)
151 {
152 LBSLOGD(CACHED_LOCATIONS_CALLBACK, "CachedLocationsCallbackHost::OnCacheLocationsReport");
153 }
154
DeleteHandler()155 void CachedLocationsCallbackHost::DeleteHandler()
156 {
157 std::unique_lock<std::mutex> guard(mutex_);
158 if (handlerCb_ == nullptr || env_ == nullptr) {
159 LBSLOGE(CACHED_LOCATIONS_CALLBACK, "handler or env is nullptr.");
160 return;
161 }
162 auto context = new (std::nothrow) AsyncContext(env_);
163 if (context == nullptr) {
164 LBSLOGE(CACHED_LOCATIONS_CALLBACK, "context == nullptr.");
165 return;
166 }
167 context->env = env_;
168 context->callback[SUCCESS_CALLBACK] = handlerCb_;
169 DeleteQueueWork(context);
170 handlerCb_ = nullptr;
171 }
172 } // namespace Location
173 } // namespace OHOS
174