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()176 NapiBluetoothBleCentralManagerCallback::NapiBluetoothBleCentralManagerCallback()
177 : eventSubscribe_(REGISTER_BLE_FIND_DEVICE_TYPE, BT_MODULE_NAME)
178 {}
179
GetInstance(void)180 NapiBluetoothBleCentralManagerCallback &NapiBluetoothBleCentralManagerCallback::GetInstance(void)
181 {
182 static NapiBluetoothBleCentralManagerCallback instance;
183 return instance;
184 }
185
OnSysScanCallback(const BleScanResult & result,const std::string & type)186 static void OnSysScanCallback(const BleScanResult &result, const std::string &type)
187 {
188 std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
189 auto sysObservers = GetSysBLEObserver();
190 if (!sysObservers.empty() &&
191 sysObservers.find(type) != sysObservers.end()) {
192 SysOnScanCallBack(sysObservers, result);
193 }
194 }
195
OnScanCallback(const BleScanResult & result)196 void NapiBluetoothBleCentralManagerCallback::OnScanCallback(const BleScanResult &result)
197 {
198 HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
199 // system scan
200 OnSysScanCallback(result, REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
201
202 auto nativeObject = std::make_shared<NapiNativeBleScanResult>(result);
203 eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeObject);
204 }
205
UvQueueWorkOnBleBatchScanResultsEvent(uv_work_t * work,const std::vector<BleScanResult> & results)206 void NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent(
207 uv_work_t *work, const std::vector<BleScanResult> &results)
208 {
209 HILOGI("enter");
210
211 if (work == nullptr) {
212 HILOGE("work is null");
213 return;
214 }
215 auto callbackData = (AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
216 decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
217 std::vector<BleScanResult>> *)work->data;
218 if (callbackData == nullptr) {
219 HILOGE("callbackData is null");
220 return;
221 }
222
223 napi_value result = 0;
224 napi_value callback = 0;
225 napi_value undefined = 0;
226 napi_value callResult = 0;
227 napi_get_undefined(callbackData->env, &undefined);
228 ConvertScanResult(results, callbackData->env, result);
229 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
230 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
231 }
232
OnBleBatchScanResultsEvent(const std::vector<BleScanResult> & results)233 void NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results)
234 {
235 HILOGI("enter, scan result size: %{public}zu", results.size());
236 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallbackInfoByType(REGISTER_BLE_FIND_DEVICE_TYPE);
237 if (callbackInfo == nullptr) {
238 HILOGI("This callback is not registered by ability.");
239 return;
240 }
241 uv_loop_s *loop = nullptr;
242 napi_get_uv_event_loop(callbackInfo->env_, &loop);
243 if (loop == nullptr) {
244 HILOGE("loop instance is nullptr");
245 return;
246 }
247
248 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
249 decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
250 std::vector<BleScanResult>>();
251 if (callbackData == nullptr) {
252 HILOGE("new callbackData failed");
253 return;
254 }
255
256 callbackData->object = this;
257 callbackData->function = &NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent;
258 callbackData->env = callbackInfo->env_;
259 callbackData->callback = callbackInfo->callback_;
260 callbackData->data = results;
261
262 uv_work_t *work = new (std::nothrow) uv_work_t;
263 if (work == nullptr) {
264 HILOGE("new work failed");
265 delete callbackData;
266 callbackData = nullptr;
267 return;
268 }
269
270 work->data = static_cast<void *>(callbackData);
271
272 int ret = uv_queue_work(
273 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
274 if (ret != 0) {
275 delete callbackData;
276 callbackData = nullptr;
277 delete work;
278 work = nullptr;
279 }
280 }
281
OnStartOrStopScanEvent(int resultCode,bool isStartScan)282 void NapiBluetoothBleCentralManagerCallback::OnStartOrStopScanEvent(int resultCode, bool isStartScan)
283 {
284 HILOGD("resultCode: %{public}d, isStartScan: %{public}d", resultCode, isStartScan);
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 uv_queue_work(
324 loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEScan);
325 }
326
ToNapiValue(napi_env env) const327 napi_value NapiNativeBleScanResult::ToNapiValue(napi_env env) const
328 {
329 napi_value object = 0;
330 std::vector<BleScanResult> results {scanResult_};
331 ConvertScanResult(results, env, object);
332 return object;
333 }
334 } // namespace Bluetooth
335 } // namespace OHOS
336