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