• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(bool isLatestNapiBleScannerObj)176 NapiBluetoothBleCentralManagerCallback::NapiBluetoothBleCentralManagerCallback(bool isLatestNapiBleScannerObj)
177     : eventSubscribe_(REGISTER_BLE_FIND_DEVICE_TYPE, BT_MODULE_NAME)
178 {
179     isLatestNapiBleScannerObj_ = isLatestNapiBleScannerObj;
180 }
181 
GetInstance(void)182 NapiBluetoothBleCentralManagerCallback &NapiBluetoothBleCentralManagerCallback::GetInstance(void)
183 {
184     static NapiBluetoothBleCentralManagerCallback instance(false);
185     return instance;
186 }
187 
OnSysScanCallback(const BleScanResult & result,const std::string & type)188 static void OnSysScanCallback(const BleScanResult &result, const std::string &type)
189 {
190     std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
191     auto sysObservers = GetSysBLEObserver();
192     if (!sysObservers.empty() &&
193         sysObservers.find(type) != sysObservers.end()) {
194         SysOnScanCallBack(sysObservers, result);
195     }
196 }
197 
OnScanCallback(const BleScanResult & result)198 void NapiBluetoothBleCentralManagerCallback::OnScanCallback(const BleScanResult &result)
199 {
200     HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
201     // system scan
202     OnSysScanCallback(result, REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
203 
204     if (isLatestNapiBleScannerObj_) {
205         auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(result, ScanReportType::ON_FOUND);
206         eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
207     } else {
208         auto nativeObject = std::make_shared<NapiNativeBleScanResult>(result);
209         eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeObject);
210     }
211 }
212 
OnFoundOrLostCallback(const BleScanResult & result,uint8_t callbackType)213 void NapiBluetoothBleCentralManagerCallback::OnFoundOrLostCallback(const BleScanResult &result, uint8_t callbackType)
214 {
215     HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
216 
217     ScanReportType scanReportType = ScanReportType::ON_FOUND;
218     ConvertScanReportType(scanReportType, callbackType);
219 
220     if (isLatestNapiBleScannerObj_) {
221         auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(result, scanReportType);
222         eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
223     } else {
224         HILOGE("error callback.");
225     }
226 }
227 
ConvertScanReportType(ScanReportType & scanReportType,uint8_t callbackType)228 void NapiBluetoothBleCentralManagerCallback::ConvertScanReportType(
229     ScanReportType &scanReportType, uint8_t callbackType)
230 {
231     if (callbackType == BLE_SCAN_CALLBACK_TYPE_FIRST_MATCH) {
232         scanReportType = ScanReportType::ON_FOUND;
233     } else if (callbackType == BLE_SCAN_CALLBACK_TYPE_LOST_MATCH) {
234         scanReportType = ScanReportType::ON_LOST;
235     }
236 }
237 
UvQueueWorkOnBleBatchScanResultsEvent(uv_work_t * work,const std::vector<BleScanResult> & results)238 void NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent(
239     uv_work_t *work, const std::vector<BleScanResult> &results)
240 {
241     HILOGI("enter");
242 
243     if (work == nullptr) {
244         HILOGE("work is null");
245         return;
246     }
247     auto callbackData = (AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
248         decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
249         std::vector<BleScanResult>> *)work->data;
250     if (callbackData == nullptr) {
251         HILOGE("callbackData is null");
252         return;
253     }
254 
255     napi_value result = 0;
256     napi_value callback = 0;
257     napi_value undefined = 0;
258     napi_value callResult = 0;
259     napi_get_undefined(callbackData->env, &undefined);
260     ConvertScanResult(results, callbackData->env, result);
261     napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
262     napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
263 }
264 
OnBleBatchScanResultsEvent(const std::vector<BleScanResult> & results)265 void NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results)
266 {
267     HILOGI("enter, scan result size: %{public}zu", results.size());
268     std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallbackInfoByType(REGISTER_BLE_FIND_DEVICE_TYPE);
269     if (callbackInfo == nullptr) {
270         HILOGI("This callback is not registered by ability.");
271         return;
272     }
273     uv_loop_s *loop = nullptr;
274     napi_get_uv_event_loop(callbackInfo->env_, &loop);
275     if (loop == nullptr) {
276         HILOGE("loop instance is nullptr");
277         return;
278     }
279 
280     auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
281         decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
282         std::vector<BleScanResult>>();
283     if (callbackData == nullptr) {
284         HILOGE("new callbackData failed");
285         return;
286     }
287 
288     callbackData->object = this;
289     callbackData->function = &NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent;
290     callbackData->env = callbackInfo->env_;
291     callbackData->callback = callbackInfo->callback_;
292     callbackData->data = results;
293 
294     uv_work_t *work = new (std::nothrow) uv_work_t;
295     if (work == nullptr) {
296         HILOGE("new work failed");
297         delete callbackData;
298         callbackData = nullptr;
299         return;
300     }
301 
302     work->data = static_cast<void *>(callbackData);
303 
304     int ret = uv_queue_work(
305         loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
306     if (ret != 0) {
307         delete callbackData;
308         callbackData = nullptr;
309         delete work;
310         work = nullptr;
311     }
312 }
313 
OnStartOrStopScanEvent(int resultCode,bool isStartScan)314 void NapiBluetoothBleCentralManagerCallback::OnStartOrStopScanEvent(int resultCode, bool isStartScan)
315 {
316     HILOGI("resultCode: %{public}d, isStartScan: %{public}d", resultCode, isStartScan);
317     auto napiIsStartScan = std::make_shared<NapiNativeBool>(isStartScan);
318     if (isStartScan) {
319         AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_START_SCAN, napiIsStartScan, resultCode);
320     } else {
321         AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_STOP_SCAN, napiIsStartScan, resultCode);
322     }
323 
324     std::array<std::shared_ptr<BluetoothCallbackInfo>, ARGS_SIZE_THREE> callbackInfos;
325     {
326         std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
327         auto observers = GetSysBLEObserver();
328         if (observers.empty()) {
329             HILOGD("observers is empty.");
330             return;
331         }
332         if (observers.find(REGISTER_SYS_BLE_SCAN_TYPE) == observers.end()) {
333             HILOGI("sys BEL callback is not registered by ability.");
334             return;
335         }
336         callbackInfos = observers[REGISTER_SYS_BLE_SCAN_TYPE];
337     }
338 
339     uv_loop_s *loop = nullptr;
340     napi_get_uv_event_loop(callbackInfos[PARAM0]->env_, &loop);
341     if (loop == nullptr) {
342         HILOGE("loop instance is nullptr");
343         return;
344     }
345     uv_work_t *work = new (std::nothrow) uv_work_t;
346     if (work == nullptr) {
347         HILOGE("create uv_work_t failed!");
348         return;
349     }
350     SysBLEStartScanCallbackData *data = new (std::nothrow) SysBLEStartScanCallbackData();
351     if (data == nullptr) {
352         HILOGE("create SysBLECallbackData failed!");
353         delete work;
354         return;
355     }
356     data->resultCode = resultCode;
357     data->env = callbackInfos[PARAM0]->env_;
358     data->callbackSuccess = callbackInfos[PARAM0]->callback_;
359     data->callbackFail = callbackInfos[PARAM1]->callback_;
360     data->callbackComplete = callbackInfos[PARAM2]->callback_;
361     work->data = static_cast<void *>(data);
362     uv_queue_work(
363         loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEScan);
364 }
365 
ToNapiValue(napi_env env) const366 napi_value NapiNativeBleScanResult::ToNapiValue(napi_env env) const
367 {
368     napi_value object = 0;
369     std::vector<BleScanResult> results {scanResult_};
370     ConvertScanResult(results, env, object);
371     return object;
372 }
373 
ToNapiValue(napi_env env) const374 napi_value NapiNativeBleScanReport::ToNapiValue(napi_env env) const
375 {
376     napi_value scanReport = nullptr;
377     napi_create_object(env, &scanReport);
378 
379     std::vector<BleScanResult> results {scanResult_};
380     int32_t scanReportType = static_cast<int32_t>(scanReportType_);
381 
382     napi_value reportType = nullptr;
383     napi_create_int32(env, scanReportType, &reportType);
384     napi_set_named_property(env, scanReport, "reportType", reportType);
385 
386     napi_value scanResult = nullptr;
387     ConvertScanResult(results, env, scanResult);
388     napi_set_named_property(env, scanReport, "scanResult", scanResult);
389 
390     return scanReport;
391 }
392 }  // namespace Bluetooth
393 }  // namespace OHOS
394