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