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