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()176 NapiBluetoothBleCentralManagerCallback::NapiBluetoothBleCentralManagerCallback()
177     : eventSubscribe_(REGISTER_BLE_FIND_DEVICE_TYPE, BT_MODULE_NAME)
178 {}
179 
GetInstance(void)180 NapiBluetoothBleCentralManagerCallback &NapiBluetoothBleCentralManagerCallback::GetInstance(void)
181 {
182     static NapiBluetoothBleCentralManagerCallback instance;
183     return instance;
184 }
185 
OnSysScanCallback(const BleScanResult & result,const std::string & type)186 static void OnSysScanCallback(const BleScanResult &result, const std::string &type)
187 {
188     std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
189     auto sysObservers = GetSysBLEObserver();
190     if (!sysObservers.empty() &&
191         sysObservers.find(type) != sysObservers.end()) {
192         SysOnScanCallBack(sysObservers, result);
193     }
194 }
195 
OnScanCallback(const BleScanResult & result)196 void NapiBluetoothBleCentralManagerCallback::OnScanCallback(const BleScanResult &result)
197 {
198     HILOGD("enter, remote device address: %{public}s", GET_ENCRYPT_ADDR(result.GetPeripheralDevice()));
199     // system scan
200     OnSysScanCallback(result, REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
201 
202     auto nativeObject = std::make_shared<NapiNativeBleScanResult>(result);
203     eventSubscribe_.PublishEvent(REGISTER_BLE_FIND_DEVICE_TYPE, nativeObject);
204 }
205 
UvQueueWorkOnBleBatchScanResultsEvent(uv_work_t * work,const std::vector<BleScanResult> & results)206 void NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent(
207     uv_work_t *work, const std::vector<BleScanResult> &results)
208 {
209     HILOGI("enter");
210 
211     if (work == nullptr) {
212         HILOGE("work is null");
213         return;
214     }
215     auto callbackData = (AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
216         decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
217         std::vector<BleScanResult>> *)work->data;
218     if (callbackData == nullptr) {
219         HILOGE("callbackData is null");
220         return;
221     }
222 
223     napi_value result = 0;
224     napi_value callback = 0;
225     napi_value undefined = 0;
226     napi_value callResult = 0;
227     napi_get_undefined(callbackData->env, &undefined);
228     ConvertScanResult(results, callbackData->env, result);
229     napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
230     napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
231 }
232 
OnBleBatchScanResultsEvent(const std::vector<BleScanResult> & results)233 void NapiBluetoothBleCentralManagerCallback::OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results)
234 {
235     HILOGI("enter, scan result size: %{public}zu", results.size());
236     std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallbackInfoByType(REGISTER_BLE_FIND_DEVICE_TYPE);
237     if (callbackInfo == nullptr) {
238         HILOGI("This callback is not registered by ability.");
239         return;
240     }
241     uv_loop_s *loop = nullptr;
242     napi_get_uv_event_loop(callbackInfo->env_, &loop);
243     if (loop == nullptr) {
244         HILOGE("loop instance is nullptr");
245         return;
246     }
247 
248     auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothBleCentralManagerCallback,
249         decltype(&NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent),
250         std::vector<BleScanResult>>();
251     if (callbackData == nullptr) {
252         HILOGE("new callbackData failed");
253         return;
254     }
255 
256     callbackData->object = this;
257     callbackData->function = &NapiBluetoothBleCentralManagerCallback::UvQueueWorkOnBleBatchScanResultsEvent;
258     callbackData->env = callbackInfo->env_;
259     callbackData->callback = callbackInfo->callback_;
260     callbackData->data = results;
261 
262     uv_work_t *work = new (std::nothrow) uv_work_t;
263     if (work == nullptr) {
264         HILOGE("new work failed");
265         delete callbackData;
266         callbackData = nullptr;
267         return;
268     }
269 
270     work->data = static_cast<void *>(callbackData);
271 
272     int ret = uv_queue_work(
273         loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
274     if (ret != 0) {
275         delete callbackData;
276         callbackData = nullptr;
277         delete work;
278         work = nullptr;
279     }
280 }
281 
OnStartOrStopScanEvent(int resultCode,bool isStartScan)282 void NapiBluetoothBleCentralManagerCallback::OnStartOrStopScanEvent(int resultCode, bool isStartScan)
283 {
284     HILOGD("resultCode: %{public}d, isStartScan: %{public}d", resultCode, isStartScan);
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     uv_queue_work(
324         loop, work, [](uv_work_t *work) {}, AfterWorkCallbackToSysBLEScan);
325 }
326 
ToNapiValue(napi_env env) const327 napi_value NapiNativeBleScanResult::ToNapiValue(napi_env env) const
328 {
329     napi_value object = 0;
330     std::vector<BleScanResult> results {scanResult_};
331     ConvertScanResult(results, env, object);
332     return object;
333 }
334 }  // namespace Bluetooth
335 }  // namespace OHOS
336