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