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
OnBleBatchScanResultsEvent(const std::vector<BleScanResult> & results)223 void NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results)
224 {
225 if (isLatestNapiBleScannerObj_) {
226 auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(results, ScanReportType::ON_BATCH);
227 eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
228 }
229 }
230
OnFoundOrLostCallback(const BleScanResult & result,uint8_t callbackType)231 void NapiBluetoothBleCentralManagerCallback::OnFoundOrLostCallback(const BleScanResult &result, uint8_t callbackType)
232 {
233 HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
234
235 ScanReportType scanReportType = ScanReportType::ON_FOUND;
236 ConvertScanReportType(scanReportType, callbackType);
237
238 if (isLatestNapiBleScannerObj_) {
239 auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(result, scanReportType);
240 eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
241 } else {
242 HILOGE("error callback.");
243 }
244 }
245
ConvertScanReportType(ScanReportType & scanReportType,uint8_t callbackType)246 void NapiBluetoothBleCentralManagerCallback::ConvertScanReportType(
247 ScanReportType &scanReportType, uint8_t callbackType)
248 {
249 if (callbackType == BLE_SCAN_CALLBACK_TYPE_FIRST_MATCH) {
250 scanReportType = ScanReportType::ON_FOUND;
251 } else if (callbackType == BLE_SCAN_CALLBACK_TYPE_LOST_MATCH) {
252 scanReportType = ScanReportType::ON_LOST;
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
StartBLESysScanTask(int resultCode)283 static void StartBLESysScanTask(int resultCode)
284 {
285 std::array<std::shared_ptr<BluetoothCallbackInfo>, ARGS_SIZE_THREE> callbackInfos;
286 {
287 std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
288 auto observers = GetSysBLEObserver();
289 if (observers.empty()) {
290 HILOGD("observers is empty.");
291 return;
292 }
293 if (observers.find(REGISTER_SYS_BLE_SCAN_TYPE) == observers.end()) {
294 HILOGI("sys BEL callback is not registered by ability.");
295 return;
296 }
297 callbackInfos = observers[REGISTER_SYS_BLE_SCAN_TYPE];
298 }
299
300 uv_loop_s *loop = nullptr;
301 napi_get_uv_event_loop(callbackInfos[PARAM0]->env_, &loop);
302 if (loop == nullptr) {
303 HILOGE("loop instance is nullptr");
304 return;
305 }
306 uv_work_t *work = new (std::nothrow) uv_work_t;
307 if (work == nullptr) {
308 HILOGE("create uv_work_t failed!");
309 return;
310 }
311 SysBLEStartScanCallbackData *data = new (std::nothrow) SysBLEStartScanCallbackData();
312 if (data == nullptr) {
313 HILOGE("create SysBLECallbackData failed!");
314 delete work;
315 return;
316 }
317 data->resultCode = resultCode;
318 data->env = callbackInfos[PARAM0]->env_;
319 data->callbackSuccess = callbackInfos[PARAM0]->callback_;
320 data->callbackFail = callbackInfos[PARAM1]->callback_;
321 data->callbackComplete = callbackInfos[PARAM2]->callback_;
322 work->data = static_cast<void *>(data);
323 int ret = uv_queue_work(
324 loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEScan);
325 if (ret != 0) {
326 delete data;
327 data = nullptr;
328 delete work;
329 work = nullptr;
330 }
331 }
332
OnStartOrStopScanEvent(int resultCode,bool isStartScan)333 void NapiBluetoothBleCentralManagerCallback::OnStartOrStopScanEvent(int resultCode, bool isStartScan)
334 {
335 HILOGD("resultCode: %{public}d, isStartScan: %{public}d", resultCode, isStartScan);
336 auto napiIsStartScan = std::make_shared<NapiNativeBool>(isStartScan);
337 if (isStartScan) {
338 AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_START_SCAN, napiIsStartScan, resultCode);
339 } else {
340 AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_STOP_SCAN, napiIsStartScan, resultCode);
341 }
342
343 StartBLESysScanTask(resultCode);
344 }
345
ToNapiValue(napi_env env) const346 napi_value NapiNativeBleScanResult::ToNapiValue(napi_env env) const
347 {
348 napi_value object = 0;
349 std::vector<BleScanResult> results {scanResult_};
350 ConvertScanResult(results, env, object);
351 return object;
352 }
353
ToNapiValue(napi_env env) const354 napi_value NapiNativeBleScanReport::ToNapiValue(napi_env env) const
355 {
356 napi_value scanReport = nullptr;
357 napi_create_object(env, &scanReport);
358
359 int32_t scanReportType = static_cast<int32_t>(scanReportType_);
360
361 napi_value reportType = nullptr;
362 napi_create_int32(env, scanReportType, &reportType);
363 napi_set_named_property(env, scanReport, "reportType", reportType);
364
365 napi_value scanResult = nullptr;
366 ConvertScanResult(scanResults_, env, scanResult);
367 napi_set_named_property(env, scanReport, "scanResult", scanResult);
368
369 return scanReport;
370 }
371 } // namespace Bluetooth
372 } // namespace OHOS
373