1 /*
2 * Copyright (C) 2021-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 "napi_bluetooth_ble_central_manager_callback.h"
16
17 #include "bluetooth_log.h"
18 #include "napi_bluetooth_utils.h"
19 #include "securec.h"
20
21 namespace OHOS {
22 namespace Bluetooth {
23 namespace {
24 struct SysBLEStartScanCallbackData {
25 napi_env env;
26 napi_ref callbackSuccess = nullptr;
27 napi_ref callbackFail = nullptr;
28 napi_ref callbackComplete = nullptr;
29 int32_t resultCode = 0;
30 };
31
32 struct SysBLEDeviceFoundCallbackData {
33 napi_env env;
34 napi_ref callbackSuccess = nullptr;
35 napi_ref callbackFail = nullptr;
36 std::shared_ptr<BleScanResult> result;
37 };
ConvertScanResult(const std::vector<BleScanResult> & results,const napi_env & env,napi_value & scanResultArray,bool isSysInterface=false)38 void ConvertScanResult(const std::vector<BleScanResult> &results, const napi_env &env, napi_value &scanResultArray,
39 bool isSysInterface = false)
40 {
41 HILOGI("ConvertScanResult called");
42 napi_create_array(env, &scanResultArray);
43 size_t count = 0;
44 for (auto bleScanResult : results) {
45 napi_value result = nullptr;
46 napi_value value = nullptr;
47 napi_create_object(env, &result);
48 napi_create_string_utf8(
49 env, bleScanResult.GetPeripheralDevice().GetDeviceAddr().c_str(), NAPI_AUTO_LENGTH, &value);
50 std::string propertyName = "deviceId";
51 if (isSysInterface) {
52 propertyName = "addr";
53 }
54 napi_set_named_property(env, result, propertyName.c_str(), value);
55 napi_create_int32(env, bleScanResult.GetRssi(), &value);
56 napi_set_named_property(env, result, "rssi", value);
57 if (isSysInterface) {
58 HILOGI("ConvertScanResult isSysInterface");
59 napi_create_string_utf8(env, "random", NAPI_AUTO_LENGTH, &value);
60 napi_set_named_property(env, result, "addrType", value);
61 napi_create_int32(env, 1, &value);
62 napi_set_named_property(env, result, "txpower", value);
63 }
64 uint8_t *native = nullptr;
65 napi_value buffer = nullptr;
66 napi_create_arraybuffer(env, bleScanResult.GetPayload().size(), reinterpret_cast<void **>(&native), &buffer);
67 if (memcpy_s(native, bleScanResult.GetPayload().size(), bleScanResult.GetPayload().data(),
68 bleScanResult.GetPayload().size()) != EOK) {
69 HILOGE("ConvertScanResult memcpy_s fail");
70 return;
71 }
72 napi_create_typedarray(env, napi_uint8_array, bleScanResult.GetPayload().size(), buffer, 0, &value);
73 napi_set_named_property(env, result, "data", value);
74 napi_set_element(env, scanResultArray, count, result);
75 ++count;
76 }
77 }
78
AfterWorkCallbackToSysBLEScan(uv_work_t * work,int status)79 void AfterWorkCallbackToSysBLEScan(uv_work_t *work, int status)
80 {
81 if (work == nullptr) {
82 return;
83 }
84
85 std::unique_ptr<SysBLEStartScanCallbackData> data(static_cast<SysBLEStartScanCallbackData *>(work->data));
86
87 const napi_env &env = data->env;
88
89 napi_value funcComplete = nullptr;
90 napi_value callbackResult = nullptr;
91 napi_value undefine = nullptr;
92 napi_get_undefined(env, &undefine);
93 napi_get_reference_value(env, data->callbackComplete, &funcComplete);
94 if (data->resultCode == 0) {
95 napi_value funcSuccess = nullptr;
96 napi_get_reference_value(env, data->callbackSuccess, &funcSuccess);
97 napi_call_function(env, undefine, funcSuccess, 0, nullptr, &callbackResult);
98 } else {
99 napi_value funcFail = nullptr;
100 napi_get_reference_value(env, data->callbackFail, &funcFail);
101 napi_value callbackValue[] {nullptr, nullptr};
102 napi_create_string_utf8(env, "sys startBLEScan fail", NAPI_AUTO_LENGTH, &callbackValue[0]);
103 napi_create_int32(env, data->resultCode, &callbackValue[1]);
104 napi_call_function(env, undefine, funcFail, ARGS_SIZE_TWO, callbackValue, &callbackResult);
105 }
106 napi_call_function(env, undefine, funcComplete, 0, nullptr, &callbackResult);
107 }
108
AfterWorkCallbackToSysBLEDeviceFound(uv_work_t * work,int status)109 void AfterWorkCallbackToSysBLEDeviceFound(uv_work_t *work, int status)
110 {
111 if (work == nullptr) {
112 return;
113 }
114
115 std::unique_ptr<SysBLEDeviceFoundCallbackData> data(static_cast<SysBLEDeviceFoundCallbackData *>(work->data));
116 const napi_env &env = data->env;
117
118 napi_value result = nullptr;
119 std::vector<BleScanResult> scanResults;
120 scanResults.push_back(*(data->result));
121 ConvertScanResult(scanResults, env, result, true);
122
123 napi_value object = nullptr;
124 napi_create_object(env, &object);
125 napi_set_named_property(env, object, "devices", result);
126 napi_value callbackResult = nullptr;
127 napi_value undefine = nullptr;
128 napi_get_undefined(env, &undefine);
129 napi_value funcSuccess = nullptr;
130 napi_get_reference_value(env, data->callbackSuccess, &funcSuccess);
131 napi_call_function(env, undefine, funcSuccess, ARGS_SIZE_ONE, &object, &callbackResult);
132 }
133
SysOnScanCallBack(sysBLEMap & observers,const BleScanResult & result)134 void SysOnScanCallBack(sysBLEMap &observers, const BleScanResult &result)
135 {
136 auto callbackInfos = observers[REGISTER_SYS_BLE_FIND_DEVICE_TYPE];
137 uv_loop_s *loop = nullptr;
138 napi_get_uv_event_loop(callbackInfos[PARAM0]->env_, &loop);
139 if (loop == nullptr) {
140 HILOGE("loop instance is nullptr");
141 return;
142 }
143 uv_work_t *work = new (std::nothrow) uv_work_t;
144 if (work == nullptr) {
145 HILOGE("create uv_work_t failed!");
146 return;
147 }
148
149 SysBLEDeviceFoundCallbackData *data = new (std::nothrow) SysBLEDeviceFoundCallbackData();
150 if (data == nullptr) {
151 HILOGE("create SysBLECallbackData failed!");
152 delete work;
153 return;
154 }
155
156 data->env = callbackInfos[PARAM0]->env_;
157 data->callbackSuccess = callbackInfos[PARAM0]->callback_;
158 data->callbackFail = callbackInfos[PARAM1]->callback_;
159 data->result = std::make_shared<BleScanResult>(result);
160 work->data = static_cast<void *>(data);
161 uv_queue_work(
162 loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEDeviceFound);
163 }
164 } // namespace
165
UvQueueWorkOnScanCallback(uv_work_t * work,std::shared_ptr<BleScanResult> & result)166 void NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnScanCallback(
167 uv_work_t *work, std::shared_ptr<BleScanResult> &result)
168 {
169 HILOGI("OnScanCallback uv_work_t start");
170
171 if (work == nullptr) {
172 HILOGE("work is null");
173 return;
174 }
175 auto callbackData = (AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
176 decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnScanCallback),
177 std::shared_ptr<BleScanResult>> *)work->data;
178 if (callbackData == nullptr) {
179 HILOGE("callbackData is null");
180 return;
181 }
182 napi_value napiResult = 0;
183 napi_value callback = 0;
184 napi_value undefined = 0;
185 napi_value callResult = 0;
186 napi_get_undefined(callbackData->env, &undefined);
187 std::vector<BleScanResult> results;
188 results.push_back(*result);
189 ConvertScanResult(results, callbackData->env, napiResult);
190 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
191 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &napiResult, &callResult);
192 }
193
OnScanCallback(const BleScanResult & result)194 void NapiBluetoothBleCentralManagerCallback::OnScanCallback(const BleScanResult &result)
195 {
196 HILOGI("NapiBluetoothBleCentralManagerCallback::OnScanCallback called");
197 auto sysObservers = GetSysBLEObserver();
198 if (sysObservers.find(REGISTER_SYS_BLE_FIND_DEVICE_TYPE) != sysObservers.end()) {
199 SysOnScanCallBack(sysObservers, result);
200 }
201 std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> observers = GetObserver();
202 if (!observers[REGISTER_BLE_FIND_DEVICE_TYPE]) {
203 HILOGE("NapiBluetoothHostObserver::OnStateChanged: This callback is not registered by ability.");
204 return;
205 }
206 HILOGD("NapiBluetoothHostObserver::OnStateChanged: %{public}s is registered by ability",
207 REGISTER_BLE_FIND_DEVICE_TYPE.c_str());
208 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = observers[REGISTER_BLE_FIND_DEVICE_TYPE];
209 uv_loop_s *loop = nullptr;
210 napi_get_uv_event_loop(callbackInfo->env_, &loop);
211 if (loop == nullptr) {
212 HILOGE("loop instance is nullptr");
213 return;
214 }
215
216 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
217 decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnScanCallback),
218 std::shared_ptr<BleScanResult>>();
219 if (callbackData == nullptr) {
220 HILOGE("new callbackData failed");
221 return;
222 }
223
224 callbackData->object = this;
225 callbackData->function = &NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnScanCallback;
226 callbackData->env = callbackInfo->env_;
227 callbackData->callback = callbackInfo->callback_;
228 callbackData->data = std::make_shared<BleScanResult>(result);
229
230 uv_work_t *work = new (std::nothrow) uv_work_t;
231 if (work == nullptr) {
232 HILOGE("new work failed");
233 delete callbackData;
234 callbackData = nullptr;
235 return;
236 }
237
238 work->data = (void *)callbackData;
239
240 int ret = uv_queue_work(
241 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
242 if (ret != 0) {
243 delete callbackData;
244 callbackData = nullptr;
245 delete work;
246 work = nullptr;
247 }
248 }
249
UvQueueWorkOnBleBatchScanResultsEvent(uv_work_t * work,const std::vector<BleScanResult> & results)250 void NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent(
251 uv_work_t *work, const std::vector<BleScanResult> &results)
252 {
253 HILOGI("OnBleBatchScanResultsEvent uv_work_t start");
254
255 if (work == nullptr) {
256 HILOGE("work is null");
257 return;
258 }
259 auto callbackData = (AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
260 decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
261 std::vector<BleScanResult>> *)work->data;
262 if (callbackData == nullptr) {
263 HILOGE("callbackData is null");
264 return;
265 }
266
267 napi_value result = 0;
268 napi_value callback = 0;
269 napi_value undefined = 0;
270 napi_value callResult = 0;
271 napi_get_undefined(callbackData->env, &undefined);
272 ConvertScanResult(results, callbackData->env, result);
273 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
274 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
275 }
276
OnBleBatchScanResultsEvent(const std::vector<BleScanResult> & results)277 void NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results)
278 {
279 HILOGI("NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent called");
280 std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> observers = GetObserver();
281 if (!observers[REGISTER_BLE_FIND_DEVICE_TYPE]) {
282 HILOGE("NapiBluetoothHostObserver::OnStateChanged: This callback is not registered by ability.");
283 return;
284 }
285 HILOGD("NapiBluetoothHostObserver::OnStateChanged: %{public}s is registered by ability",
286 REGISTER_BLE_FIND_DEVICE_TYPE.c_str());
287 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = observers[REGISTER_BLE_FIND_DEVICE_TYPE];
288 uv_loop_s *loop = nullptr;
289 napi_get_uv_event_loop(callbackInfo->env_, &loop);
290 if (loop == nullptr) {
291 HILOGE("loop instance is nullptr");
292 return;
293 }
294
295 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
296 decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
297 std::vector<BleScanResult>>();
298 if (callbackData == nullptr) {
299 HILOGE("new callbackData failed");
300 return;
301 }
302
303 callbackData->object = this;
304 callbackData->function = &NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent;
305 callbackData->env = callbackInfo->env_;
306 callbackData->callback = callbackInfo->callback_;
307 callbackData->data = results;
308
309 uv_work_t *work = new (std::nothrow) uv_work_t;
310 if (work == nullptr) {
311 HILOGE("new work failed");
312 delete callbackData;
313 callbackData = nullptr;
314 return;
315 }
316
317 work->data = (void *)callbackData;
318
319 int ret = uv_queue_work(
320 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
321 if (ret != 0) {
322 delete callbackData;
323 callbackData = nullptr;
324 delete work;
325 work = nullptr;
326 }
327 }
328
OnStartScanFailed(int resultCode)329 void NapiBluetoothBleCentralManagerCallback::OnStartScanFailed(int resultCode)
330 {
331 HILOGI("NapiBluetoothBleCentralManagerCallback::OnStartScanFailed called, resultCode is %{public}d", resultCode);
332 auto observers = GetSysBLEObserver();
333 if (observers.find(REGISTER_SYS_BLE_SCAN_TYPE) == observers.end()) {
334 HILOGE("sys BEL callback is not registered by ability.");
335 return;
336 }
337 auto callbackInfos = observers[REGISTER_SYS_BLE_SCAN_TYPE];
338 uv_loop_s *loop = nullptr;
339 napi_get_uv_event_loop(callbackInfos[PARAM0]->env_, &loop);
340 if (loop == nullptr) {
341 HILOGE("loop instance is nullptr");
342 return;
343 }
344 uv_work_t *work = new (std::nothrow) uv_work_t;
345 if (work == nullptr) {
346 HILOGE("create uv_work_t failed!");
347 return;
348 }
349
350 SysBLEStartScanCallbackData *data = new (std::nothrow) SysBLEStartScanCallbackData();
351 if (data == nullptr) {
352 HILOGE("create SysBLECallbackData failed!");
353 delete work;
354 return;
355 }
356
357 data->resultCode = resultCode;
358 data->env = callbackInfos[PARAM0]->env_;
359 data->callbackSuccess = callbackInfos[PARAM0]->callback_;
360 data->callbackFail = callbackInfos[PARAM1]->callback_;
361 data->callbackComplete = callbackInfos[PARAM2]->callback_;
362 work->data = static_cast<void *>(data);
363 uv_queue_work(
364 loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEScan);
365 }
366 } // namespace Bluetooth
367 } // namespace OHOS
368