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