• 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     delete work;
117     work = nullptr;
118 }
119 
AfterWorkCallbackToSysBLEDeviceFound(uv_work_t * work,int status)120 void AfterWorkCallbackToSysBLEDeviceFound(uv_work_t *work, int status)
121 {
122     if (work == nullptr) {
123         return;
124     }
125 
126     std::unique_ptr<SysBLEDeviceFoundCallbackData> data(static_cast<SysBLEDeviceFoundCallbackData *>(work->data));
127     const napi_env &env = data->env;
128 
129     NapiHandleScope scope(env);
130     napi_value result = nullptr;
131     std::vector<BleScanResult> scanResults;
132     scanResults.push_back(*(data->result));
133     ConvertScanResult(scanResults, env, result, true);
134 
135     napi_value object = nullptr;
136     napi_create_object(env, &object);
137     napi_set_named_property(env, object, "devices", result);
138     napi_value callbackResult = nullptr;
139     napi_value undefine = nullptr;
140     napi_get_undefined(env, &undefine);
141     napi_value funcSuccess = nullptr;
142     napi_get_reference_value(env, data->callbackSuccess, &funcSuccess);
143     napi_call_function(env, undefine, funcSuccess, ARGS_SIZE_ONE, &object, &callbackResult);
144     delete work;
145     work = nullptr;
146 }
147 
SysOnScanCallBack(sysBLEMap & observers,const BleScanResult & result)148 void SysOnScanCallBack(sysBLEMap &observers, const BleScanResult &result)
149 {
150     auto callbackInfos = observers[REGISTER_SYS_BLE_FIND_DEVICE_TYPE];
151     uv_loop_s *loop = nullptr;
152     napi_get_uv_event_loop(callbackInfos[PARAM0]->env_, &loop);
153     if (loop == nullptr) {
154         HILOGE("loop instance is nullptr");
155         return;
156     }
157     uv_work_t *work = new (std::nothrow) uv_work_t;
158     if (work == nullptr) {
159         HILOGE("create uv_work_t failed!");
160         return;
161     }
162 
163     SysBLEDeviceFoundCallbackData *data = new (std::nothrow) SysBLEDeviceFoundCallbackData();
164     if (data == nullptr) {
165         HILOGE("create SysBLECallbackData failed!");
166         delete work;
167         return;
168     }
169 
170     data->env = callbackInfos[PARAM0]->env_;
171     data->callbackSuccess = callbackInfos[PARAM0]->callback_;
172     data->callbackFail = callbackInfos[PARAM1]->callback_;
173     data->result = std::make_shared<BleScanResult>(result);
174     work->data = static_cast<void *>(data);
175     int ret = uv_queue_work(
176         loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEDeviceFound);
177     if (ret != 0) {
178         delete data;
179         data = nullptr;
180         delete work;
181         work = nullptr;
182     }
183 }
184 } // namespace
185 
NapiBluetoothBleCentralManagerCallback(bool isLatestNapiBleScannerObj)186 NapiBluetoothBleCentralManagerCallback::NapiBluetoothBleCentralManagerCallback(bool isLatestNapiBleScannerObj)
187     : eventSubscribe_(REGISTER_BLE_FIND_DEVICE_TYPE, BT_MODULE_NAME)
188 {
189     isLatestNapiBleScannerObj_ = isLatestNapiBleScannerObj;
190 }
191 
GetInstance(void)192 NapiBluetoothBleCentralManagerCallback &NapiBluetoothBleCentralManagerCallback::GetInstance(void)
193 {
194     static NapiBluetoothBleCentralManagerCallback instance(false);
195     return instance;
196 }
197 
OnSysScanCallback(const BleScanResult & result,const std::string & type)198 static void OnSysScanCallback(const BleScanResult &result, const std::string &type)
199 {
200     std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
201     auto sysObservers = GetSysBLEObserver();
202     if (!sysObservers.empty() &&
203         sysObservers.find(type) != sysObservers.end()) {
204         SysOnScanCallBack(sysObservers, result);
205     }
206 }
207 
OnScanCallback(const BleScanResult & result)208 void NapiBluetoothBleCentralManagerCallback::OnScanCallback(const BleScanResult &result)
209 {
210     HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
211     // system scan
212     OnSysScanCallback(result, REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
213 
214     if (isLatestNapiBleScannerObj_) {
215         auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(result, ScanReportType::ON_FOUND);
216         eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
217     } else {
218         auto nativeObject = std::make_shared<NapiNativeBleScanResult>(result);
219         eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeObject);
220     }
221 }
222 
OnBleBatchScanResultsEvent(const std::vector<BleScanResult> & results)223 void NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results)
224 {
225     if (isLatestNapiBleScannerObj_) {
226         auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(results, ScanReportType::ON_BATCH);
227         eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
228     }
229 }
230 
OnFoundOrLostCallback(const BleScanResult & result,uint8_t callbackType)231 void NapiBluetoothBleCentralManagerCallback::OnFoundOrLostCallback(const BleScanResult &result, uint8_t callbackType)
232 {
233     HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
234 
235     ScanReportType scanReportType = ScanReportType::ON_FOUND;
236     ConvertScanReportType(scanReportType, callbackType);
237 
238     if (isLatestNapiBleScannerObj_) {
239         auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(result, scanReportType);
240         eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
241     } else {
242         HILOGE("error callback.");
243     }
244 }
245 
ConvertScanReportType(ScanReportType & scanReportType,uint8_t callbackType)246 void NapiBluetoothBleCentralManagerCallback::ConvertScanReportType(
247     ScanReportType &scanReportType, uint8_t callbackType)
248 {
249     if (callbackType == BLE_SCAN_CALLBACK_TYPE_FIRST_MATCH) {
250         scanReportType = ScanReportType::ON_FOUND;
251     } else if (callbackType == BLE_SCAN_CALLBACK_TYPE_LOST_MATCH) {
252         scanReportType = ScanReportType::ON_LOST;
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 
StartBLESysScanTask(int resultCode)283 static void StartBLESysScanTask(int resultCode)
284 {
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     int ret = uv_queue_work(
324         loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEScan);
325     if (ret != 0) {
326         delete data;
327         data = nullptr;
328         delete work;
329         work = nullptr;
330     }
331 }
332 
OnStartOrStopScanEvent(int resultCode,bool isStartScan)333 void NapiBluetoothBleCentralManagerCallback::OnStartOrStopScanEvent(int resultCode, bool isStartScan)
334 {
335     HILOGD("resultCode: %{public}d, isStartScan: %{public}d", resultCode, isStartScan);
336     auto napiIsStartScan = std::make_shared<NapiNativeBool>(isStartScan);
337     if (isStartScan) {
338         AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_START_SCAN, napiIsStartScan, resultCode);
339     } else {
340         AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_STOP_SCAN, napiIsStartScan, resultCode);
341     }
342 
343     StartBLESysScanTask(resultCode);
344 }
345 
ToNapiValue(napi_env env) const346 napi_value NapiNativeBleScanResult::ToNapiValue(napi_env env) const
347 {
348     napi_value object = 0;
349     std::vector<BleScanResult> results {scanResult_};
350     ConvertScanResult(results, env, object);
351     return object;
352 }
353 
ToNapiValue(napi_env env) const354 napi_value NapiNativeBleScanReport::ToNapiValue(napi_env env) const
355 {
356     napi_value scanReport = nullptr;
357     napi_create_object(env, &scanReport);
358 
359     int32_t scanReportType = static_cast<int32_t>(scanReportType_);
360 
361     napi_value reportType = nullptr;
362     napi_create_int32(env, scanReportType, &reportType);
363     napi_set_named_property(env, scanReport, "reportType", reportType);
364 
365     napi_value scanResult = nullptr;
366     ConvertScanResult(scanResults_, env, scanResult);
367     napi_set_named_property(env, scanReport, "scanResult", scanResult);
368 
369     return scanReport;
370 }
371 }  // namespace Bluetooth
372 }  // namespace OHOS
373