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 }
117
AfterWorkCallbackToSysBLEDeviceFound(uv_work_t * work,int status)118 void AfterWorkCallbackToSysBLEDeviceFound(uv_work_t *work, int status)
119 {
120 if (work == nullptr) {
121 return;
122 }
123
124 std::unique_ptr<SysBLEDeviceFoundCallbackData> data(static_cast<SysBLEDeviceFoundCallbackData *>(work->data));
125 const napi_env &env = data->env;
126
127 NapiHandleScope scope(env);
128 napi_value result = nullptr;
129 std::vector<BleScanResult> scanResults;
130 scanResults.push_back(*(data->result));
131 ConvertScanResult(scanResults, env, result, true);
132
133 napi_value object = nullptr;
134 napi_create_object(env, &object);
135 napi_set_named_property(env, object, "devices", result);
136 napi_value callbackResult = nullptr;
137 napi_value undefine = nullptr;
138 napi_get_undefined(env, &undefine);
139 napi_value funcSuccess = nullptr;
140 napi_get_reference_value(env, data->callbackSuccess, &funcSuccess);
141 napi_call_function(env, undefine, funcSuccess, ARGS_SIZE_ONE, &object, &callbackResult);
142 }
143
SysOnScanCallBack(sysBLEMap & observers,const BleScanResult & result)144 void SysOnScanCallBack(sysBLEMap &observers, const BleScanResult &result)
145 {
146 auto callbackInfos = observers[REGISTER_SYS_BLE_FIND_DEVICE_TYPE];
147 uv_loop_s *loop = nullptr;
148 napi_get_uv_event_loop(callbackInfos[PARAM0]->env_, &loop);
149 if (loop == nullptr) {
150 HILOGE("loop instance is nullptr");
151 return;
152 }
153 uv_work_t *work = new (std::nothrow) uv_work_t;
154 if (work == nullptr) {
155 HILOGE("create uv_work_t failed!");
156 return;
157 }
158
159 SysBLEDeviceFoundCallbackData *data = new (std::nothrow) SysBLEDeviceFoundCallbackData();
160 if (data == nullptr) {
161 HILOGE("create SysBLECallbackData failed!");
162 delete work;
163 return;
164 }
165
166 data->env = callbackInfos[PARAM0]->env_;
167 data->callbackSuccess = callbackInfos[PARAM0]->callback_;
168 data->callbackFail = callbackInfos[PARAM1]->callback_;
169 data->result = std::make_shared<BleScanResult>(result);
170 work->data = static_cast<void *>(data);
171 uv_queue_work(
172 loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEDeviceFound);
173 }
174 } // namespace
175
NapiBluetoothBleCentralManagerCallback(bool isLatestNapiBleScannerObj)176 NapiBluetoothBleCentralManagerCallback::NapiBluetoothBleCentralManagerCallback(bool isLatestNapiBleScannerObj)
177 : eventSubscribe_(REGISTER_BLE_FIND_DEVICE_TYPE, BT_MODULE_NAME)
178 {
179 isLatestNapiBleScannerObj_ = isLatestNapiBleScannerObj;
180 }
181
GetInstance(void)182 NapiBluetoothBleCentralManagerCallback &NapiBluetoothBleCentralManagerCallback::GetInstance(void)
183 {
184 static NapiBluetoothBleCentralManagerCallback instance(false);
185 return instance;
186 }
187
OnSysScanCallback(const BleScanResult & result,const std::string & type)188 static void OnSysScanCallback(const BleScanResult &result, const std::string &type)
189 {
190 std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
191 auto sysObservers = GetSysBLEObserver();
192 if (!sysObservers.empty() &&
193 sysObservers.find(type) != sysObservers.end()) {
194 SysOnScanCallBack(sysObservers, result);
195 }
196 }
197
OnScanCallback(const BleScanResult & result)198 void NapiBluetoothBleCentralManagerCallback::OnScanCallback(const BleScanResult &result)
199 {
200 HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
201 // system scan
202 OnSysScanCallback(result, REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
203
204 if (isLatestNapiBleScannerObj_) {
205 auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(result, ScanReportType::ON_FOUND);
206 eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
207 } else {
208 auto nativeObject = std::make_shared<NapiNativeBleScanResult>(result);
209 eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeObject);
210 }
211 }
212
OnFoundOrLostCallback(const BleScanResult & result,uint8_t callbackType)213 void NapiBluetoothBleCentralManagerCallback::OnFoundOrLostCallback(const BleScanResult &result, uint8_t callbackType)
214 {
215 HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
216
217 ScanReportType scanReportType = ScanReportType::ON_FOUND;
218 ConvertScanReportType(scanReportType, callbackType);
219
220 if (isLatestNapiBleScannerObj_) {
221 auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(result, scanReportType);
222 eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
223 } else {
224 HILOGE("error callback.");
225 }
226 }
227
ConvertScanReportType(ScanReportType & scanReportType,uint8_t callbackType)228 void NapiBluetoothBleCentralManagerCallback::ConvertScanReportType(
229 ScanReportType &scanReportType, uint8_t callbackType)
230 {
231 if (callbackType == BLE_SCAN_CALLBACK_TYPE_FIRST_MATCH) {
232 scanReportType = ScanReportType::ON_FOUND;
233 } else if (callbackType == BLE_SCAN_CALLBACK_TYPE_LOST_MATCH) {
234 scanReportType = ScanReportType::ON_LOST;
235 }
236 }
237
UvQueueWorkOnBleBatchScanResultsEvent(uv_work_t * work,const std::vector<BleScanResult> & results)238 void NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent(
239 uv_work_t *work, const std::vector<BleScanResult> &results)
240 {
241 HILOGI("enter");
242
243 if (work == nullptr) {
244 HILOGE("work is null");
245 return;
246 }
247 auto callbackData = (AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
248 decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
249 std::vector<BleScanResult>> *)work->data;
250 if (callbackData == nullptr) {
251 HILOGE("callbackData is null");
252 return;
253 }
254
255 napi_value result = 0;
256 napi_value callback = 0;
257 napi_value undefined = 0;
258 napi_value callResult = 0;
259 napi_get_undefined(callbackData->env, &undefined);
260 ConvertScanResult(results, callbackData->env, result);
261 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
262 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
263 }
264
OnBleBatchScanResultsEvent(const std::vector<BleScanResult> & results)265 void NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results)
266 {
267 HILOGI("enter, scan result size: %{public}zu", results.size());
268 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallbackInfoByType(REGISTER_BLE_FIND_DEVICE_TYPE);
269 if (callbackInfo == nullptr) {
270 HILOGI("This callback is not registered by ability.");
271 return;
272 }
273 uv_loop_s *loop = nullptr;
274 napi_get_uv_event_loop(callbackInfo->env_, &loop);
275 if (loop == nullptr) {
276 HILOGE("loop instance is nullptr");
277 return;
278 }
279
280 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
281 decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
282 std::vector<BleScanResult>>();
283 if (callbackData == nullptr) {
284 HILOGE("new callbackData failed");
285 return;
286 }
287
288 callbackData->object = this;
289 callbackData->function = &NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent;
290 callbackData->env = callbackInfo->env_;
291 callbackData->callback = callbackInfo->callback_;
292 callbackData->data = results;
293
294 uv_work_t *work = new (std::nothrow) uv_work_t;
295 if (work == nullptr) {
296 HILOGE("new work failed");
297 delete callbackData;
298 callbackData = nullptr;
299 return;
300 }
301
302 work->data = static_cast<void *>(callbackData);
303
304 int ret = uv_queue_work(
305 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
306 if (ret != 0) {
307 delete callbackData;
308 callbackData = nullptr;
309 delete work;
310 work = nullptr;
311 }
312 }
313
OnStartOrStopScanEvent(int resultCode,bool isStartScan)314 void NapiBluetoothBleCentralManagerCallback::OnStartOrStopScanEvent(int resultCode, bool isStartScan)
315 {
316 HILOGI("resultCode: %{public}d, isStartScan: %{public}d", resultCode, isStartScan);
317 auto napiIsStartScan = std::make_shared<NapiNativeBool>(isStartScan);
318 if (isStartScan) {
319 AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_START_SCAN, napiIsStartScan, resultCode);
320 } else {
321 AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_STOP_SCAN, napiIsStartScan, resultCode);
322 }
323
324 std::array<std::shared_ptr<BluetoothCallbackInfo>, ARGS_SIZE_THREE> callbackInfos;
325 {
326 std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
327 auto observers = GetSysBLEObserver();
328 if (observers.empty()) {
329 HILOGD("observers is empty.");
330 return;
331 }
332 if (observers.find(REGISTER_SYS_BLE_SCAN_TYPE) == observers.end()) {
333 HILOGI("sys BEL callback is not registered by ability.");
334 return;
335 }
336 callbackInfos = observers[REGISTER_SYS_BLE_SCAN_TYPE];
337 }
338
339 uv_loop_s *loop = nullptr;
340 napi_get_uv_event_loop(callbackInfos[PARAM0]->env_, &loop);
341 if (loop == nullptr) {
342 HILOGE("loop instance is nullptr");
343 return;
344 }
345 uv_work_t *work = new (std::nothrow) uv_work_t;
346 if (work == nullptr) {
347 HILOGE("create uv_work_t failed!");
348 return;
349 }
350 SysBLEStartScanCallbackData *data = new (std::nothrow) SysBLEStartScanCallbackData();
351 if (data == nullptr) {
352 HILOGE("create SysBLECallbackData failed!");
353 delete work;
354 return;
355 }
356 data->resultCode = resultCode;
357 data->env = callbackInfos[PARAM0]->env_;
358 data->callbackSuccess = callbackInfos[PARAM0]->callback_;
359 data->callbackFail = callbackInfos[PARAM1]->callback_;
360 data->callbackComplete = callbackInfos[PARAM2]->callback_;
361 work->data = static_cast<void *>(data);
362 uv_queue_work(
363 loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEScan);
364 }
365
ToNapiValue(napi_env env) const366 napi_value NapiNativeBleScanResult::ToNapiValue(napi_env env) const
367 {
368 napi_value object = 0;
369 std::vector<BleScanResult> results {scanResult_};
370 ConvertScanResult(results, env, object);
371 return object;
372 }
373
ToNapiValue(napi_env env) const374 napi_value NapiNativeBleScanReport::ToNapiValue(napi_env env) const
375 {
376 napi_value scanReport = nullptr;
377 napi_create_object(env, &scanReport);
378
379 std::vector<BleScanResult> results {scanResult_};
380 int32_t scanReportType = static_cast<int32_t>(scanReportType_);
381
382 napi_value reportType = nullptr;
383 napi_create_int32(env, scanReportType, &reportType);
384 napi_set_named_property(env, scanReport, "reportType", reportType);
385
386 napi_value scanResult = nullptr;
387 ConvertScanResult(results, env, scanResult);
388 napi_set_named_property(env, scanReport, "scanResult", scanResult);
389
390 return scanReport;
391 }
392 } // namespace Bluetooth
393 } // namespace OHOS
394