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