• 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 
OnFoundOrLostCallback(const BleScanResult & result,uint8_t callbackType)223 void NapiBluetoothBleCentralManagerCallback::OnFoundOrLostCallback(const BleScanResult &result, uint8_t callbackType)
224 {
225     HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
226 
227     ScanReportType scanReportType = ScanReportType::ON_FOUND;
228     ConvertScanReportType(scanReportType, callbackType);
229 
230     if (isLatestNapiBleScannerObj_) {
231         auto nativeBleScanReportObj = std::make_shared<NapiNativeBleScanReport>(result, scanReportType);
232         eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeBleScanReportObj);
233     } else {
234         HILOGE("error callback.");
235     }
236 }
237 
ConvertScanReportType(ScanReportType & scanReportType,uint8_t callbackType)238 void NapiBluetoothBleCentralManagerCallback::ConvertScanReportType(
239     ScanReportType &scanReportType, uint8_t callbackType)
240 {
241     if (callbackType == BLE_SCAN_CALLBACK_TYPE_FIRST_MATCH) {
242         scanReportType = ScanReportType::ON_FOUND;
243     } else if (callbackType == BLE_SCAN_CALLBACK_TYPE_LOST_MATCH) {
244         scanReportType = ScanReportType::ON_LOST;
245     }
246 }
247 
UvQueueWorkOnBleBatchScanResultsEvent(uv_work_t * work,const std::vector<BleScanResult> & results)248 void NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent(
249     uv_work_t *work, const std::vector<BleScanResult> &results)
250 {
251     HILOGI("enter");
252 
253     if (work == nullptr) {
254         HILOGE("work is null");
255         return;
256     }
257     auto callbackData = (AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
258         decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
259         std::vector<BleScanResult>> *)work->data;
260     if (callbackData == nullptr) {
261         HILOGE("callbackData is null");
262         return;
263     }
264 
265     napi_value result = 0;
266     napi_value callback = 0;
267     napi_value undefined = 0;
268     napi_value callResult = 0;
269     napi_get_undefined(callbackData->env, &undefined);
270     ConvertScanResult(results, callbackData->env, result);
271     napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
272     napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
273 }
274 
OnBleBatchScanResultsEvent(const std::vector<BleScanResult> & results)275 void NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results)
276 {
277     HILOGI("enter, scan result size: %{public}zu", results.size());
278     std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallbackInfoByType(REGISTER_BLE_FIND_DEVICE_TYPE);
279     if (callbackInfo == nullptr) {
280         HILOGI("This callback is not registered by ability.");
281         return;
282     }
283     uv_loop_s *loop = nullptr;
284     napi_get_uv_event_loop(callbackInfo->env_, &loop);
285     if (loop == nullptr) {
286         HILOGE("loop instance is nullptr");
287         return;
288     }
289 
290     auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
291         decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
292         std::vector<BleScanResult>>();
293     if (callbackData == nullptr) {
294         HILOGE("new callbackData failed");
295         return;
296     }
297 
298     callbackData->object = this;
299     callbackData->function = &NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent;
300     callbackData->env = callbackInfo->env_;
301     callbackData->callback = callbackInfo->callback_;
302     callbackData->data = results;
303 
304     uv_work_t *work = new (std::nothrow) uv_work_t;
305     if (work == nullptr) {
306         HILOGE("new work failed");
307         delete callbackData;
308         callbackData = nullptr;
309         return;
310     }
311 
312     work->data = static_cast<void *>(callbackData);
313 
314     int ret = uv_queue_work(
315         loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
316     if (ret != 0) {
317         delete callbackData;
318         callbackData = nullptr;
319         delete work;
320         work = nullptr;
321     }
322 }
323 
StartBLESysScanTask(int resultCode)324 static void StartBLESysScanTask(int resultCode)
325 {
326     std::array<std::shared_ptr<BluetoothCallbackInfo>, ARGS_SIZE_THREE> callbackInfos;
327     {
328         std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
329         auto observers = GetSysBLEObserver();
330         if (observers.empty()) {
331             HILOGD("observers is empty.");
332             return;
333         }
334         if (observers.find(REGISTER_SYS_BLE_SCAN_TYPE) == observers.end()) {
335             HILOGI("sys BEL callback is not registered by ability.");
336             return;
337         }
338         callbackInfos = observers[REGISTER_SYS_BLE_SCAN_TYPE];
339     }
340 
341     uv_loop_s *loop = nullptr;
342     napi_get_uv_event_loop(callbackInfos[PARAM0]->env_, &loop);
343     if (loop == nullptr) {
344         HILOGE("loop instance is nullptr");
345         return;
346     }
347     uv_work_t *work = new (std::nothrow) uv_work_t;
348     if (work == nullptr) {
349         HILOGE("create uv_work_t failed!");
350         return;
351     }
352     SysBLEStartScanCallbackData *data = new (std::nothrow) SysBLEStartScanCallbackData();
353     if (data == nullptr) {
354         HILOGE("create SysBLECallbackData failed!");
355         delete work;
356         return;
357     }
358     data->resultCode = resultCode;
359     data->env = callbackInfos[PARAM0]->env_;
360     data->callbackSuccess = callbackInfos[PARAM0]->callback_;
361     data->callbackFail = callbackInfos[PARAM1]->callback_;
362     data->callbackComplete = callbackInfos[PARAM2]->callback_;
363     work->data = static_cast<void *>(data);
364     int ret = uv_queue_work(
365         loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEScan);
366     if (ret != 0) {
367         delete data;
368         data = nullptr;
369         delete work;
370         work = nullptr;
371     }
372 }
373 
OnStartOrStopScanEvent(int resultCode,bool isStartScan)374 void NapiBluetoothBleCentralManagerCallback::OnStartOrStopScanEvent(int resultCode, bool isStartScan)
375 {
376     HILOGI("resultCode: %{public}d, isStartScan: %{public}d", resultCode, isStartScan);
377     auto napiIsStartScan = std::make_shared<NapiNativeBool>(isStartScan);
378     if (isStartScan) {
379         AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_START_SCAN, napiIsStartScan, resultCode);
380     } else {
381         AsyncWorkCallFunction(asyncWorkMap_, NapiAsyncType::BLE_STOP_SCAN, napiIsStartScan, resultCode);
382     }
383 
384     StartBLESysScanTask(resultCode);
385 }
386 
ToNapiValue(napi_env env) const387 napi_value NapiNativeBleScanResult::ToNapiValue(napi_env env) const
388 {
389     napi_value object = 0;
390     std::vector<BleScanResult> results {scanResult_};
391     ConvertScanResult(results, env, object);
392     return object;
393 }
394 
ToNapiValue(napi_env env) const395 napi_value NapiNativeBleScanReport::ToNapiValue(napi_env env) const
396 {
397     napi_value scanReport = nullptr;
398     napi_create_object(env, &scanReport);
399 
400     std::vector<BleScanResult> results {scanResult_};
401     int32_t scanReportType = static_cast<int32_t>(scanReportType_);
402 
403     napi_value reportType = nullptr;
404     napi_create_int32(env, scanReportType, &reportType);
405     napi_set_named_property(env, scanReport, "reportType", reportType);
406 
407     napi_value scanResult = nullptr;
408     ConvertScanResult(results, env, scanResult);
409     napi_set_named_property(env, scanReport, "scanResult", scanResult);
410 
411     return scanReport;
412 }
413 }  // namespace Bluetooth
414 }  // namespace OHOS
415