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