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.h"
16 
17 #include "napi_bluetooth_ble_advertise_callback.h"
18 #include "napi_bluetooth_ble_central_manager_callback.h"
19 #include "napi_bluetooth_error.h"
20 #include "napi_bluetooth_gatt_client.h"
21 #include "napi_bluetooth_gatt_server.h"
22 #include "napi_bluetooth_utils.h"
23 #include "napi_bluetooth_ble_utils.h"
24 
25 #include "bluetooth_ble_advertiser.h"
26 #include "bluetooth_ble_central_manager.h"
27 #include "bluetooth_errorcode.h"
28 #include "bluetooth_utils.h"
29 #include "../parser/napi_parser_utils.h"
30 #include "hitrace_meter.h"
31 
32 #include <memory>
33 namespace OHOS {
34 namespace Bluetooth {
35 namespace {
36 struct SysStopBLEContext {
37     napi_async_work work = nullptr;
38     napi_ref callbackSuccess = nullptr;
39     napi_ref callbackFail = nullptr;
40     napi_ref callbackComplete = nullptr;
41 };
42 
43 namespace {
BleAdvertiserGetInstance(void)44 std::shared_ptr<BleAdvertiser> BleAdvertiserGetInstance(void)
45 {
46     static auto instance = BleAdvertiser::CreateInstance();
47     return instance;
48 }
49 
BleCentralManagerGetInstance(void)50 BleCentralManager *BleCentralManagerGetInstance(void)
51 {
52     static BleCentralManager instance(NapiBluetoothBleCentralManagerCallback::GetInstance());
53     return &instance;
54 }
55 }  // namespace {}
56 
GetPropertyValueByNamed(napi_env env, napi_value object, std::string_view propertyName, napi_valuetype type)57 napi_value GetPropertyValueByNamed(napi_env env, napi_value object, std::string_view propertyName, napi_valuetype type)
58 {
59     napi_value value = nullptr;
60     bool hasProperty = false;
61     napi_valuetype paraType = napi_undefined;
62 
63     NAPI_CALL(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty));
64     if (hasProperty) {
65         NAPI_CALL(env, napi_get_named_property(env, object, propertyName.data(), &value));
66         NAPI_CALL(env, napi_typeof(env, value, &paraType));
67         if (paraType != type) {
68             return NapiGetNull(env);
69         }
70     }
71     return value;
72 }
73 
RegisterBLEObserver(napi_env env, napi_value val, int32_t callbackIndex, const std::string &type)74 void RegisterBLEObserver(napi_env env, napi_value val, int32_t callbackIndex, const std::string &type)
75 {
76     std::shared_ptr<BluetoothCallbackInfo> pCallbackInfo = std::make_shared<BluetoothCallbackInfo>();
77     pCallbackInfo->env_ = env;
78     napi_create_reference(env, val, 1, &pCallbackInfo->callback_);
79     RegisterSysBLEObserver(pCallbackInfo, callbackIndex, type);
80 }
81 
ParseScanParameters(napi_env env, napi_value arg, ScanOptions &info)82 bool ParseScanParameters(napi_env env, napi_value arg, ScanOptions &info)
83 {
84     napi_value interval = GetPropertyValueByNamed(env, arg, "interval", napi_number);
85     if (interval) {
86         napi_get_value_int32(env, interval, &info.interval);
87         HILOGI("Scan interval is %{public}d", info.interval);
88     } else {
89         info.interval = 0;
90     }
91 
92     std::array<std::string, ARGS_SIZE_THREE> funcArray {"success", "fail", "complete"};
93 
94     for (size_t i = 0; i < funcArray.size(); i++) {
95         napi_value value = GetPropertyValueByNamed(env, arg, funcArray[i], napi_function);
96         if (value) {
97             RegisterBLEObserver(env, value, i, REGISTER_SYS_BLE_SCAN_TYPE);
98         } else {
99             UnregisterSysBLEObserver(REGISTER_SYS_BLE_SCAN_TYPE);
100             return false;
101         }
102     }
103     return true;
104 }
105 
SysStartBLEScan(napi_env env, napi_callback_info info)106 napi_value SysStartBLEScan(napi_env env, napi_callback_info info)
107 {
108     size_t argc = ARGS_SIZE_ONE;
109     napi_value argv[] = {nullptr};
110     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
111     if (argc != 1) {
112         return NapiGetNull(env);
113     }
114 
115     napi_valuetype valueType = napi_undefined;
116     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
117     if (valueType != napi_object) {
118         return NapiGetNull(env);
119     }
120     ScanOptions scanOptions;
121     if (!ParseScanParameters(env, argv[PARAM0], scanOptions)) {
122         HILOGE("SysStartBLEScan Input parameter parsing failed!");
123         return NapiGetNull(env);
124     }
125 
126     std::vector<BleScanFilter> scanFilters;
127     BleScanFilter emptyFilter;
128     scanFilters.push_back(emptyFilter);
129     BleScanSettings settings;
130     settings.SetReportDelay(scanOptions.interval);
131     settings.SetScanMode(static_cast<int32_t>(scanOptions.dutyMode));
132     settings.SetPhy(static_cast<int32_t>(scanOptions.phyType));
133 
134     BleCentralManagerGetInstance()->StartScan(settings, scanFilters);
135     return NapiGetNull(env);
136 }
137 
SysStopBLEScanExec(napi_env env, void *data)138 void SysStopBLEScanExec(napi_env env, void *data)
139 {
140     HILOGI("SysStopBLEScanExec");
141     BleCentralManagerGetInstance()->StopScan();
142     UnregisterSysBLEObserver(REGISTER_SYS_BLE_SCAN_TYPE);
143 }
144 
SysStopBLEScanComplete(napi_env env, napi_status status, void *data)145 void SysStopBLEScanComplete(napi_env env, napi_status status, void *data)
146 {
147     NAPI_CALL_RETURN_VOID(env, (data == nullptr ? napi_invalid_arg : napi_ok));
148     std::unique_ptr<SysStopBLEContext> context(static_cast<SysStopBLEContext *>(data));
149 
150     napi_value undefine = nullptr;
151     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefine));
152     napi_value funcComplete = nullptr;
153     napi_value funcSuccess = nullptr;
154     napi_value callbackResult = nullptr;
155     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, context->callbackSuccess, &funcSuccess));
156     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefine, funcSuccess, 0, nullptr, &callbackResult));
157     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, context->callbackComplete, &funcComplete));
158     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefine, funcComplete, 0, nullptr, &callbackResult));
159     NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callbackSuccess));
160     NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callbackComplete));
161     NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callbackFail));
162     NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, context->work));
163     HILOGI("SysStopBLEScanComplete end");
164 }
165 
SysStopBLEScan(napi_env env, napi_callback_info info)166 napi_value SysStopBLEScan(napi_env env, napi_callback_info info)
167 {
168     size_t argc = ARGS_SIZE_ONE;
169     napi_value argv[] = {nullptr};
170     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
171     if (argc != 1) {
172         return NapiGetNull(env);
173     }
174 
175     napi_valuetype valueType = napi_undefined;
176     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
177     if (valueType != napi_object) {
178         return NapiGetNull(env);
179     }
180 
181     std::unique_ptr<SysStopBLEContext> context = std::make_unique<SysStopBLEContext>();
182 
183     std::array<std::string, ARGS_SIZE_THREE> funcArray {"success", "fail", "complete"};
184     for (size_t i = 0; i < funcArray.size(); i++) {
185         napi_value value = GetPropertyValueByNamed(env, argv[PARAM0], funcArray[i], napi_function);
186         if (value) {
187             napi_create_reference(env, value, 1,
188                 &(i == PARAM0 ? context->callbackSuccess :
189                                 (i == PARAM1 ? context->callbackFail : context->callbackComplete)));
190         } else {
191             HILOGE("SysStopBLEScan Input parameter parsing failed!");
192             return NapiGetNull(env);
193         }
194     }
195 
196     napi_value resourceName = nullptr;
197     NAPI_CALL(env, napi_create_string_utf8(env, "SysStopBLEScan", NAPI_AUTO_LENGTH, &resourceName));
198     SysStopBLEContext *pContext = context.release();
199     napi_status status = napi_create_async_work(env, nullptr, resourceName, SysStopBLEScanExec,
200         SysStopBLEScanComplete, static_cast<void *>(pContext), &pContext->work);
201     if (status != napi_ok) {
202         delete pContext;
203         return NapiGetNull(env);
204     }
205 
206     if (napi_queue_async_work(env, pContext->work) != napi_ok) {
207         delete pContext;
208     }
209     return NapiGetNull(env);
210 }
211 
ParseDeviceFoundParameters(napi_env env, napi_value arg)212 bool ParseDeviceFoundParameters(napi_env env, napi_value arg)
213 {
214     std::array<std::string, ARGS_SIZE_TWO> funcArray {"success", "fail"};
215 
216     for (size_t i = 0; i < funcArray.size(); i++) {
217         napi_value value = GetPropertyValueByNamed(env, arg, funcArray[i], napi_function);
218         if (value) {
219             RegisterBLEObserver(env, value, i, REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
220         } else {
221             UnregisterSysBLEObserver(REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
222             return false;
223         }
224     }
225     return true;
226 }
227 
SysSubscribeBLEFound(napi_env env, napi_callback_info info)228 napi_value SysSubscribeBLEFound(napi_env env, napi_callback_info info)
229 {
230     size_t argc = ARGS_SIZE_ONE;
231     napi_value argv[] = {nullptr};
232     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
233     if (argc != 1) {
234         return NapiGetNull(env);
235     }
236 
237     napi_valuetype valueType = napi_undefined;
238     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
239     if (valueType != napi_object) {
240         return NapiGetNull(env);
241     }
242     if (!ParseDeviceFoundParameters(env, argv[PARAM0])) {
243         HILOGE("SysSubscribeBLEFound Input parameter parsing failed!");
244     }
245     return NapiGetNull(env);
246 }
247 
SysUnsubscribeBLEFound(napi_env env, napi_callback_info info)248 napi_value SysUnsubscribeBLEFound(napi_env env, napi_callback_info info)
249 {
250     UnregisterSysBLEObserver(REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
251     return NapiGetNull(env);
252 }
253 } // namespace
254 
DefineSystemBLEInterface(napi_env env, napi_value exports)255 void DefineSystemBLEInterface(napi_env env, napi_value exports)
256 {
257     napi_property_descriptor desc[] = {
258         DECLARE_NAPI_FUNCTION("startBLEScan", SysStartBLEScan),
259         DECLARE_NAPI_FUNCTION("stopBLEScan", SysStopBLEScan),
260         DECLARE_NAPI_FUNCTION("subscribeBLEFound", SysSubscribeBLEFound),
261         DECLARE_NAPI_FUNCTION("unsubscribeBLEFound", SysUnsubscribeBLEFound),
262     };
263     HITRACE_METER_NAME(HITRACE_TAG_OHOS, "ble:napi_define_properties");
264     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
265 }
266 
267 using NapiBluetoothOnOffFunc = std::function<napi_status(napi_env env, napi_callback_info info)>;
268 
NapiBluetoothBleOnOffExecute(napi_env env, napi_callback_info info, NapiBluetoothOnOffFunc bleCentralManagerFunc, NapiBluetoothOnOffFunc bleAdvertiserFunc)269 static napi_status NapiBluetoothBleOnOffExecute(napi_env env, napi_callback_info info,
270     NapiBluetoothOnOffFunc bleCentralManagerFunc, NapiBluetoothOnOffFunc bleAdvertiserFunc)
271 {
272     std::string type = "";
273     NAPI_BT_CALL_RETURN(NapiGetOnOffCallbackName(env, info, type));
274 
275     napi_status status = napi_ok;
276     if (type == REGISTER_BLE_ADVERTISING_STATE_INFO_TYPE) {
277         status = bleAdvertiserFunc(env, info);
278     } else if (type == REGISTER_BLE_FIND_DEVICE_TYPE) {
279         status = bleCentralManagerFunc(env, info);
280     } else {
281         HILOGE("Unsupported callback: %{public}s", type.c_str());
282         status = napi_invalid_arg;
283     }
284     return status;
285 }
286 
On(napi_env env, napi_callback_info info)287 static napi_value On(napi_env env, napi_callback_info info)
288 {
289     auto bleCentralManagerFunc = [](napi_env env, napi_callback_info info) {
290         return NapiBluetoothBleCentralManagerCallback::GetInstance().eventSubscribe_.Register(env, info);
291     };
292     auto bleAdvertiserFunc =  [](napi_env env, napi_callback_info info) {
293         return NapiBluetoothBleAdvertiseCallback::GetInstance()->eventSubscribe_.Register(env, info);
294     };
295 
296     auto status = NapiBluetoothBleOnOffExecute(env, info, bleCentralManagerFunc, bleAdvertiserFunc);
297     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
298     return NapiGetUndefinedRet(env);
299 }
300 
Off(napi_env env, napi_callback_info info)301 static napi_value Off(napi_env env, napi_callback_info info)
302 {
303     auto bleCentralManagerFunc = [](napi_env env, napi_callback_info info) {
304         return NapiBluetoothBleCentralManagerCallback::GetInstance().eventSubscribe_.Deregister(env, info);
305     };
306     auto bleAdvertiserFunc =  [](napi_env env, napi_callback_info info) {
307         return NapiBluetoothBleAdvertiseCallback::GetInstance()->eventSubscribe_.Deregister(env, info);
308     };
309 
310     auto status = NapiBluetoothBleOnOffExecute(env, info, bleCentralManagerFunc, bleAdvertiserFunc);
311     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
312     return NapiGetUndefinedRet(env);
313 }
314 
DefineBLEJSObject(napi_env env, napi_value exports)315 void DefineBLEJSObject(napi_env env, napi_value exports)
316 {
317     HILOGD("enter");
318     PropertyInit(env, exports);
319     napi_property_descriptor desc[] = {
320         DECLARE_NAPI_FUNCTION("createGattServer", NapiGattServer::CreateGattServer),
321         DECLARE_NAPI_FUNCTION("createGattClientDevice", NapiGattClient::CreateGattClientDevice),
322         DECLARE_NAPI_FUNCTION("startBLEScan", StartBLEScan),
323         DECLARE_NAPI_FUNCTION("stopBLEScan", StopBLEScan),
324         DECLARE_NAPI_FUNCTION("on", On),
325         DECLARE_NAPI_FUNCTION("off", Off),
326         DECLARE_NAPI_FUNCTION("getConnectedBLEDevices", GetConnectedBLEDevices),
327 #ifdef BLUETOOTH_API_SINCE_10
328         DECLARE_NAPI_FUNCTION("startAdvertising", StartAdvertising),
329         DECLARE_NAPI_FUNCTION("stopAdvertising", StopAdvertising),
330         DECLARE_NAPI_FUNCTION("enableAdvertising", EnableAdvertising),
331         DECLARE_NAPI_FUNCTION("disableAdvertising", DisableAdvertising),
332 #endif
333     };
334 
335     HITRACE_METER_NAME(HITRACE_TAG_OHOS, "ble:napi_define_properties");
336 #ifdef BLUETOOTH_API_SINCE_10
337     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
338 #else
339     napi_value BLEObject = nullptr;
340     napi_create_object(env, &BLEObject);
341     napi_define_properties(env, BLEObject, sizeof(desc) / sizeof(desc[0]), desc);
342     napi_set_named_property(env, exports, "BLE", BLEObject);
343 #endif
344 }
345 
ConvertMatchMode(ScanOptions &params, int32_t matchMode)346 static void ConvertMatchMode(ScanOptions &params, int32_t matchMode)
347 {
348     switch (matchMode) {
349         case MatchMode::MATCH_MODE_AGGRESSIVE:
350             params.matchMode = MatchMode::MATCH_MODE_AGGRESSIVE;
351             break;
352         case MatchMode::MATCH_MODE_STICKY:
353             params.matchMode = MatchMode::MATCH_MODE_STICKY;
354             break;
355         default:
356             break;
357     }
358 }
359 
ConvertPhyType(ScanOptions &params, int32_t phyType)360 static void ConvertPhyType(ScanOptions &params, int32_t phyType)
361 {
362     switch (phyType) {
363         case static_cast<int32_t>(PhyType::PHY_LE_1M):
364             params.phyType = PhyType::PHY_LE_1M;
365             break;
366         case static_cast<int32_t>(PhyType::PHY_LE_2M):
367             params.phyType = PhyType::PHY_LE_2M;
368             break;
369         case static_cast<int32_t>(PhyType::PHY_LE_CODED):
370             params.phyType = PhyType::PHY_LE_CODED;
371             break;
372         case static_cast<int32_t>(PhyType::PHY_LE_ALL_SUPPORTED):
373             params.phyType = PhyType::PHY_LE_ALL_SUPPORTED;
374             break;
375         default:
376             break;
377     }
378 }
379 
ConvertDutyMode(ScanOptions &params, int32_t dutyMode)380 static void ConvertDutyMode(ScanOptions &params, int32_t dutyMode)
381 {
382     switch (dutyMode) {
383         case static_cast<int32_t>(ScanDuty::SCAN_MODE_LOW_POWER):
384             params.dutyMode = ScanDuty::SCAN_MODE_LOW_POWER;
385             break;
386         case static_cast<int32_t>(ScanDuty::SCAN_MODE_BALANCED):
387             params.dutyMode = ScanDuty::SCAN_MODE_BALANCED;
388             break;
389         case static_cast<int32_t>(ScanDuty::SCAN_MODE_LOW_LATENCY):
390             params.dutyMode = ScanDuty::SCAN_MODE_LOW_LATENCY;
391             break;
392         default:
393             break;
394     }
395 }
396 
ParseScanParameters( const napi_env &env, const napi_callback_info &info, const napi_value &scanArg, ScanOptions &params)397 static napi_status ParseScanParameters(
398     const napi_env &env, const napi_callback_info &info, const napi_value &scanArg, ScanOptions &params)
399 {
400     (void)info;
401     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, scanArg, {"interval", "dutyMode", "matchMode", "phyType"}));
402 
403     bool exist = false;
404     int32_t interval = 0;
405     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "interval", exist, interval));
406     if (exist) {
407         HILOGI("Scan interval is %{public}d", interval);
408         params.interval = interval;
409     }
410 
411     int32_t dutyMode = 0;
412     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "dutyMode", exist, dutyMode));
413     if (exist) {
414         HILOGI("Scan dutyMode is %{public}d", dutyMode);
415         ConvertDutyMode(params, dutyMode);
416     }
417 
418     int32_t matchMode = 0;
419     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "matchMode", exist, matchMode));
420     if (exist) {
421         HILOGI("Scan matchMode is %{public}d", matchMode);
422         ConvertMatchMode(params, matchMode);
423     }
424 
425     int32_t phyType = 0;
426     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "phyType", exist, phyType));
427     if (exist) {
428         HILOGI("Scan phyType is %{public}d", phyType);
429         ConvertPhyType(params, phyType);
430     }
431     return napi_ok;
432 }
433 
ParseScanFilterDeviceIdParameters( const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)434 static napi_status ParseScanFilterDeviceIdParameters(
435     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
436 {
437     bool exist = false;
438     std::string deviceId {};
439     NAPI_BT_CALL_RETURN(ParseStringParams(env, scanFilter, "deviceId", exist, deviceId));
440     if (exist) {
441         if (!IsValidAddress(deviceId)) {
442             HILOGE("Invalid deviceId: %{public}s", deviceId.c_str());
443             return napi_invalid_arg;
444         }
445 
446         HILOGI("Scan filter device id is %{public}s", GetEncryptAddr(deviceId).c_str());
447         bleScanFilter.SetDeviceId(deviceId);
448     }
449     return napi_ok;
450 }
451 
ParseScanFilterLocalNameParameters( const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)452 static napi_status ParseScanFilterLocalNameParameters(
453     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
454 {
455     bool exist = false;
456     std::string name {};
457     NAPI_BT_CALL_RETURN(ParseStringParams(env, scanFilter, "name", exist, name));
458     if (exist) {
459         if (name.empty()) {
460             HILOGE("name is empty");
461             return napi_invalid_arg;
462         }
463         HILOGI("Scan filter name is %{public}s", name.c_str());
464         bleScanFilter.SetName(name);
465     }
466     return napi_ok;
467 }
468 
ParseScanFilterServiceUuidParameters( const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)469 static napi_status ParseScanFilterServiceUuidParameters(
470     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
471 {
472     bool exist = false;
473     UUID uuid {};
474     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceUuid", exist, uuid));
475     if (exist) {
476         HILOGI("Scan filter serviceUuid is %{public}s", uuid.ToString().c_str());
477         bleScanFilter.SetServiceUuid(uuid);
478     }
479 
480     UUID uuidMask {};
481     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceUuidMask", exist, uuidMask));
482     if (exist) {
483         HILOGI("Scan filter serviceUuidMask is %{public}s", uuidMask.ToString().c_str());
484         bleScanFilter.SetServiceUuidMask(uuidMask);
485     }
486     return napi_ok;
487 }
488 
ParseScanFilterSolicitationUuidParameters( const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)489 static napi_status ParseScanFilterSolicitationUuidParameters(
490     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
491 {
492     bool exist = false;
493     UUID uuid {};
494     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceSolicitationUuid", exist, uuid));
495     if (exist) {
496         HILOGI("Scan filter serviceSolicitationUuid is %{public}s", uuid.ToString().c_str());
497         bleScanFilter.SetServiceSolicitationUuid(uuid);
498     }
499 
500     UUID uuidMask {};
501     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceSolicitationUuidMask", exist, uuidMask));
502     if (exist) {
503         HILOGI("Scan filter serviceSolicitationUuidMask is %{public}s", uuidMask.ToString().c_str());
504         bleScanFilter.SetServiceSolicitationUuidMask(uuidMask);
505     }
506     return napi_ok;
507 }
508 
ParseScanFilterServiceDataParameters( const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)509 static napi_status ParseScanFilterServiceDataParameters(
510     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
511 {
512     bool exist = false;
513     std::vector<uint8_t> data {};
514     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "serviceData", exist, data));
515     if (exist) {
516         bleScanFilter.SetServiceData(std::move(data));
517     }
518 
519     std::vector<uint8_t> dataMask {};
520     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "serviceDataMask", exist, dataMask));
521     if (exist) {
522         bleScanFilter.SetServiceDataMask(std::move(dataMask));
523     }
524     return napi_ok;
525 }
526 
ParseScanFilterManufactureDataParameters( const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)527 static napi_status ParseScanFilterManufactureDataParameters(
528     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
529 {
530     bool exist = false;
531     napi_value result;
532     NAPI_BT_CALL_RETURN(ParseNumberParams(env, scanFilter, "manufactureId", exist, result));
533     if (exist) {
534         uint32_t manufacturerId = 0;
535         NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, result, &manufacturerId));
536         bleScanFilter.SetManufacturerId(manufacturerId);
537         HILOGI("Scan filter manufacturerId is %{public}#x", manufacturerId);
538     }
539 
540     exist = false;
541     std::vector<uint8_t> data {};
542     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "manufactureData", exist, data));
543     if (exist) {
544         bleScanFilter.SetManufactureData(std::move(data));
545     }
546 
547     std::vector<uint8_t> dataMask {};
548     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "manufactureDataMask", exist, dataMask));
549     if (exist) {
550         bleScanFilter.SetManufactureDataMask(std::move(dataMask));
551     }
552     return napi_ok;
553 }
554 
ParseScanFilter(const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)555 static napi_status ParseScanFilter(const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
556 {
557     HILOGD("enter");
558     std::vector<std::string> expectedNames {"deviceId", "name", "serviceUuid", "serviceUuidMask",
559         "serviceSolicitationUuid", "serviceSolicitationUuidMask", "serviceData", "serviceDataMask", "manufactureId",
560         "manufactureData", "manufactureDataMask"};
561     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, scanFilter, expectedNames));
562 
563     NAPI_BT_CALL_RETURN(ParseScanFilterDeviceIdParameters(env, scanFilter, bleScanFilter));
564     NAPI_BT_CALL_RETURN(ParseScanFilterLocalNameParameters(env, scanFilter, bleScanFilter));
565     NAPI_BT_CALL_RETURN(ParseScanFilterServiceUuidParameters(env, scanFilter, bleScanFilter));
566     NAPI_BT_CALL_RETURN(ParseScanFilterSolicitationUuidParameters(env, scanFilter, bleScanFilter));
567     NAPI_BT_CALL_RETURN(ParseScanFilterServiceDataParameters(env, scanFilter, bleScanFilter));
568     NAPI_BT_CALL_RETURN(ParseScanFilterManufactureDataParameters(env, scanFilter, bleScanFilter));
569     return napi_ok;
570 }
571 
ParseScanFilterParameters(const napi_env &env, napi_value &args, std::vector<BleScanFilter> &params)572 static napi_status ParseScanFilterParameters(const napi_env &env, napi_value &args, std::vector<BleScanFilter> &params)
573 {
574     HILOGD("enter");
575     NAPI_BT_CALL_RETURN(NapiIsArray(env, args));
576 
577     uint32_t length = 0;
578     NAPI_BT_CALL_RETURN(napi_get_array_length(env, args, &length));
579     NAPI_BT_RETURN_IF(length == 0, "Requires array length > 0", napi_invalid_arg);
580     for (uint32_t i = 0; i < length; i++) {
581         napi_value scanFilter;
582         NAPI_BT_CALL_RETURN(napi_get_element(env, args, i, &scanFilter));
583         NAPI_BT_CALL_RETURN(NapiIsObject(env, scanFilter));
584         BleScanFilter bleScanFilter;
585         NAPI_BT_CALL_RETURN(ParseScanFilter(env, scanFilter, bleScanFilter));
586         params.push_back(bleScanFilter);
587     }
588     return napi_ok;
589 }
590 
CheckBleScanParams(napi_env env, napi_callback_info info, std::vector<BleScanFilter> &outScanfilters, BleScanSettings &outSettinngs)591 static napi_status CheckBleScanParams(napi_env env, napi_callback_info info, std::vector<BleScanFilter> &outScanfilters,
592     BleScanSettings &outSettinngs)
593 {
594     size_t argc = ARGS_SIZE_TWO;
595     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
596     napi_value thisVar = nullptr;
597     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
598     NAPI_BT_RETURN_IF((argc == 0 || argc > ARGS_SIZE_TWO), "Requires 1 or 2 arguments.", napi_invalid_arg);
599 
600     std::vector<BleScanFilter> scanfilters;
601     // Support null param
602     napi_valuetype type = napi_undefined;
603     NAPI_BT_CALL_RETURN(napi_typeof(env, argv[PARAM0], &type));
604     if (type == napi_null) {
605         BleScanFilter emptyFilter;
606         scanfilters.push_back(emptyFilter);
607     } else {
608         NAPI_BT_CALL_RETURN(ParseScanFilterParameters(env, argv[PARAM0], scanfilters));
609     }
610 
611     if (argc == ARGS_SIZE_TWO) {
612         ScanOptions scanOptions;
613         NAPI_BT_CALL_RETURN(ParseScanParameters(env, info, argv[PARAM1], scanOptions));
614         outSettinngs.SetReportDelay(scanOptions.interval);
615         outSettinngs.SetScanMode(static_cast<int32_t>(scanOptions.dutyMode));
616         outSettinngs.SetPhy(static_cast<int32_t>(scanOptions.phyType));
617     }
618 
619     outScanfilters = std::move(scanfilters);
620     return napi_ok;
621 }
622 
StartBLEScan(napi_env env, napi_callback_info info)623 napi_value StartBLEScan(napi_env env, napi_callback_info info)
624 {
625     HILOGD("enter");
626     std::vector<BleScanFilter> scanfilters;
627     BleScanSettings settings;
628     auto status = CheckBleScanParams(env, info, scanfilters, settings);
629     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
630 
631     int ret = BleCentralManagerGetInstance()->StartScan(settings, scanfilters);
632     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == NO_ERROR || ret == BT_ERR_BLE_SCAN_ALREADY_STARTED, ret);
633 
634     return NapiGetUndefinedRet(env);
635 }
636 
StopBLEScan(napi_env env, napi_callback_info info)637 napi_value StopBLEScan(napi_env env, napi_callback_info info)
638 {
639     HILOGD("enter");
640     auto status = CheckEmptyParam(env, info);
641     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
642 
643     int ret = BleCentralManagerGetInstance()->StopScan();
644     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == NO_ERROR, ret);
645     return NapiGetUndefinedRet(env);
646 }
647 
ParseAdvertisingSettingsParameters( const napi_env &env, const napi_value &object, BleAdvertiserSettings &outSettings)648 static napi_status ParseAdvertisingSettingsParameters(
649     const napi_env &env, const napi_value &object, BleAdvertiserSettings &outSettings)
650 {
651     HILOGD("enter");
652     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"interval", "txPower", "connectable"}));
653 
654     bool exist = false;
655     uint32_t interval = 0;
656     NAPI_BT_CALL_RETURN(NapiParseObjectUint32Optional(env, object, "interval", interval, exist));
657     if (exist) {
658         const uint32_t minInterval = 32;
659         const uint32_t maxInterval = 16384;
660         if (interval < minInterval || interval > maxInterval) {
661             HILOGE("Invalid interval: %{public}d", interval);
662             return napi_invalid_arg;
663         }
664         HILOGI("interval: %{public}u", interval);
665         outSettings.SetInterval(interval);
666     }
667 
668     int32_t txPower = -7; // default txPower value
669     NAPI_BT_CALL_RETURN(NapiParseObjectInt32Optional(env, object, "txPower", txPower, exist));
670     if (exist) {
671         const int32_t minTxPower = -127;
672         const int32_t maxTxPower = 1;
673         if (txPower < minTxPower || txPower > maxTxPower) {
674             HILOGE("Invalid tx power: %{public}d", txPower);
675             return napi_invalid_arg;
676         }
677         HILOGI("txPower is %{public}d", txPower);
678         outSettings.SetTxPower(txPower);
679     }
680 
681     bool connectable = false;
682     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(env, object, "connectable", connectable, exist));
683     if (exist) {
684         HILOGI("connectable: %{public}d", connectable);
685         outSettings.SetConnectable(connectable);
686     }
687     return napi_ok;
688 }
689 
ParseServiceUuidParameters(napi_env env, napi_value object, BleAdvertiserData &outData)690 static napi_status ParseServiceUuidParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
691 {
692     HILOGD("enter");
693     std::vector<UUID> vec {};
694     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "serviceUuids", vec));
695     for (size_t i = 0; i < vec.size(); ++i) {
696         outData.AddServiceUuid(vec[i]);
697         HILOGI("Service Uuid = %{public}s", vec[i].ToString().c_str());
698     }
699     return napi_ok;
700 }
701 
ParseManufactureDataParameters(napi_env env, napi_value object, BleAdvertiserData &outData)702 static napi_status ParseManufactureDataParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
703 {
704     HILOGD("enter");
705     std::vector<NapiAdvManufactureData> vec {};
706     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "manufactureData", vec));
707     for (size_t i = 0; i < vec.size(); ++i) {
708         outData.AddManufacturerData(vec[i].id, vec[i].value);
709     }
710     return napi_ok;
711 }
712 
ParseServiceDataParameters(napi_env env, napi_value object, BleAdvertiserData &outData)713 static napi_status ParseServiceDataParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
714 {
715     HILOGD("enter");
716     std::vector<NapiAdvServiceData> vec {};
717     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "serviceData", vec));
718     for (size_t i = 0; i < vec.size(); ++i) {
719         outData.AddServiceData(
720             ParcelUuid::FromString(vec[i].uuid),
721             std::string(vec[i].value.begin(), vec[i].value.end()));
722     }
723     return napi_ok;
724 }
725 
ParseAdvertisDataParameters(const napi_env &env, const napi_value &object, BleAdvertiserData &outData)726 static napi_status ParseAdvertisDataParameters(const napi_env &env,
727     const napi_value &object, BleAdvertiserData &outData)
728 {
729     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(
730         env, object, {"serviceUuids", "manufactureData", "serviceData", "includeDeviceName", "includeTxPower"}));
731 
732     NAPI_BT_CALL_RETURN(ParseServiceUuidParameters(env, object, outData));
733     NAPI_BT_CALL_RETURN(ParseManufactureDataParameters(env, object, outData));
734     NAPI_BT_CALL_RETURN(ParseServiceDataParameters(env, object, outData));
735     bool exist = false;
736     bool includeDeviceName = false;
737     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(env, object, "includeDeviceName", includeDeviceName, exist));
738     HILOGI("includeDeviceName: %{public}d", includeDeviceName);
739     outData.SetIncludeDeviceName(includeDeviceName);
740 
741     bool includeTxPower = false;
742     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(env, object, "includeTxPower", includeTxPower, exist));
743     HILOGI("includeTxPower: %{public}d", includeTxPower);
744     outData.SetIncludeTxPower(includeTxPower);
745 
746     return napi_ok;
747 }
748 
IsValidAdvertiserDuration(uint32_t duration)749 static bool IsValidAdvertiserDuration(uint32_t duration)
750 {
751     const uint32_t MIN_DURATION = 0;
752     const uint32_t MAX_DURATION = 65535;
753     if (duration < MIN_DURATION || duration > MAX_DURATION) {
754         return false;
755     }
756     return true;
757 }
758 
CheckAdvertisingDataWithDuration(napi_env env, napi_value object, BleAdvertiserSettings &outSettings, BleAdvertiserData &outAdvData, BleAdvertiserData &outRspData, uint16_t &outDuration)759 napi_status CheckAdvertisingDataWithDuration(napi_env env, napi_value object, BleAdvertiserSettings &outSettings,
760     BleAdvertiserData &outAdvData, BleAdvertiserData &outRspData, uint16_t &outDuration)
761 {
762     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"advertisingSettings", "advertisingData",
763         "advertisingResponse", "duration"}));
764 
765     napi_value advSettingsObject;
766     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
767     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, "advertisingSettings", advSettingsObject));
768     BleAdvertiserSettings settings;
769     NAPI_BT_CALL_RETURN(ParseAdvertisingSettingsParameters(env, advSettingsObject, settings));
770 
771     napi_value advDataObject;
772     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, "advertisingData", advDataObject));
773     BleAdvertiserData advData;
774     NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, advDataObject, advData));
775 
776     BleAdvertiserData advRsp;
777     if (NapiIsObjectPropertyExist(env, object, "advertisingResponse")) {
778         napi_value advRspObject;
779         NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, "advertisingResponse", advRspObject));
780         NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, advRspObject, advRsp));
781     }
782 
783     bool exist = false;
784     uint32_t duration = 0;
785     NAPI_BT_CALL_RETURN(NapiParseObjectUint32Optional(env, object, "duration", duration, exist));
786     if (exist) {
787         if (!IsValidAdvertiserDuration(duration)) {
788             HILOGE("Invalid duration: %{public}d", duration);
789             return napi_invalid_arg;
790         }
791         HILOGI("duration: %{public}u", duration);
792     }
793     outDuration = duration;
794     outSettings = std::move(settings);
795     outAdvData = std::move(advData);
796     outRspData = std::move(advRsp);
797     return napi_ok;
798 }
799 
CheckAdvertisingData(napi_env env, napi_callback_info info, BleAdvertiserSettings &outSettings, BleAdvertiserData &outAdvData, BleAdvertiserData &outRspData)800 napi_status CheckAdvertisingData(napi_env env, napi_callback_info info, BleAdvertiserSettings &outSettings,
801     BleAdvertiserData &outAdvData, BleAdvertiserData &outRspData)
802 {
803     size_t argc = ARGS_SIZE_THREE;
804     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
805     napi_value thisVar = nullptr;
806     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
807     NAPI_BT_RETURN_IF((argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE), "need 2 or 3 arguments.", napi_invalid_arg);
808 
809     BleAdvertiserSettings settings;
810     NAPI_BT_CALL_RETURN(ParseAdvertisingSettingsParameters(env, argv[PARAM0], settings));
811     BleAdvertiserData advData;
812     NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, argv[PARAM1], advData));
813     BleAdvertiserData rspData;
814     if (argc == ARGS_SIZE_THREE) {
815         NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, argv[PARAM2], rspData));
816     }
817 
818     outSettings = std::move(settings);
819     outAdvData = std::move(advData);
820     outRspData = std::move(rspData);
821     return napi_ok;
822 }
823 
StartAdvertising(napi_env env, napi_callback_info info)824 napi_value StartAdvertising(napi_env env, napi_callback_info info)
825 {
826     HILOGI("enter");
827     size_t argc = ARGS_SIZE_THREE;
828     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
829     napi_value thisVar = nullptr;
830     auto checkRes = napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL);
831     NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRes == napi_ok, BT_ERR_INVALID_PARAM);
832 
833     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
834     NAPI_BT_ASSERT_RETURN_UNDEF(env, bleAdvertiser, BT_ERR_INTERNAL_ERROR);
835 
836     BleAdvertiserSettings settings;
837     BleAdvertiserData advData;
838     BleAdvertiserData rspData;
839     if (argc != 0 && NapiIsObjectPropertyExist(env, argv[PARAM0], "advertisingSettings")) {
840         uint16_t duration = 0;
841         auto status = CheckAdvertisingDataWithDuration(env, argv[PARAM0], settings, advData, rspData, duration);
842         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
843         auto func = [settings, advData, rspData, duration, bleAdvertiser]() {
844             int ret = bleAdvertiser->StartAdvertising(
845                 settings, advData, rspData, duration, NapiBluetoothBleAdvertiseCallback::GetInstance());
846             return NapiAsyncWorkRet(ret);
847         };
848 
849         auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
850         NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
851         bool success = NapiBluetoothBleAdvertiseCallback::GetInstance()->asyncWorkMap_.TryPush(
852             NapiAsyncType::GET_ADVERTISING_HANDLE, asyncWork);
853         NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
854 
855         asyncWork->Run();
856         return asyncWork->GetRet();
857     } else {
858         auto status = CheckAdvertisingData(env, info, settings, advData, rspData);
859         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
860         int ret = bleAdvertiser->StartAdvertising(
861             settings, advData, rspData, 0, NapiBluetoothBleAdvertiseCallback::GetInstance());
862         NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == BT_NO_ERROR, ret);
863         return NapiGetUndefinedRet(env);
864     }
865 }
866 
867 #ifdef BLUETOOTH_API_SINCE_10
CheckAdvertisingEnableParams(napi_env env, napi_callback_info info, uint32_t &outAdvHandle, uint16_t &outDuration)868 napi_status CheckAdvertisingEnableParams(napi_env env, napi_callback_info info,
869     uint32_t &outAdvHandle, uint16_t &outDuration)
870 {
871     size_t argc = ARGS_SIZE_TWO;
872     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
873     napi_value thisVar = nullptr;
874     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
875     NAPI_BT_RETURN_IF((argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO), "need 1 or 2 arguments.", napi_invalid_arg);
876 
877     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, argv[PARAM0], {"advertisingId", "duration"}));
878     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, argv[PARAM0], "advertisingId", outAdvHandle));
879 
880     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
881     NAPI_BT_RETURN_IF(bleAdvertiser == nullptr, "bleAdvertiser is nullptr", napi_invalid_arg);
882     if (outAdvHandle != bleAdvertiser->GetAdvHandle(NapiBluetoothBleAdvertiseCallback::GetInstance())) {
883         HILOGE("Invalid outAdvHandle: %{public}d", outAdvHandle);
884         return napi_invalid_arg;
885     }
886 
887     bool exist = false;
888     uint32_t duration = 0;
889     NAPI_BT_CALL_RETURN(NapiParseObjectUint32Optional(env, argv[PARAM0], "duration", duration, exist));
890     if (exist) {
891         if (!IsValidAdvertiserDuration(duration)) {
892             HILOGE("Invalid duration: %{public}d", duration);
893             return napi_invalid_arg;
894         }
895         HILOGI("duration: %{public}u", duration);
896     }
897     outDuration = duration;
898 
899     return napi_ok;
900 }
901 
EnableAdvertising(napi_env env, napi_callback_info info)902 napi_value EnableAdvertising(napi_env env, napi_callback_info info)
903 {
904     HILOGI("enter");
905     uint32_t advHandle = 0xFF;
906     uint16_t duration = 0;
907     auto status = CheckAdvertisingEnableParams(env, info, advHandle, duration);
908     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
909     auto func = [advHandle, duration]() {
910         std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
911         if (bleAdvertiser == nullptr) {
912             HILOGE("bleAdvertiser is nullptr");
913             return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
914         }
915         int ret = bleAdvertiser->EnableAdvertising(
916             advHandle, duration, NapiBluetoothBleAdvertiseCallback::GetInstance());
917         return NapiAsyncWorkRet(ret);
918     };
919 
920     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
921     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
922 
923     asyncWork->Run();
924     return asyncWork->GetRet();
925 }
926 
CheckAdvertisingDisableParams(napi_env env, napi_callback_info info, uint32_t &outAdvHandle)927 napi_status CheckAdvertisingDisableParams(napi_env env, napi_callback_info info, uint32_t &outAdvHandle)
928 {
929     size_t argc = ARGS_SIZE_TWO;
930     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
931     napi_value thisVar = nullptr;
932     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
933     NAPI_BT_RETURN_IF((argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO), "need 1 or 2 arguments.", napi_invalid_arg);
934 
935     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, argv[PARAM0], {"advertisingId"}));
936     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, argv[PARAM0], "advertisingId", outAdvHandle));
937 
938     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
939     NAPI_BT_RETURN_IF(bleAdvertiser == nullptr, "bleAdvertiser is nullptr", napi_invalid_arg);
940     if (outAdvHandle != bleAdvertiser->GetAdvHandle(NapiBluetoothBleAdvertiseCallback::GetInstance())) {
941         HILOGE("Invalid outAdvHandle: %{public}d", outAdvHandle);
942         return napi_invalid_arg;
943     }
944 
945     return napi_ok;
946 }
947 
DisableAdvertising(napi_env env, napi_callback_info info)948 napi_value DisableAdvertising(napi_env env, napi_callback_info info)
949 {
950     HILOGI("enter");
951     uint32_t advHandle = 0xFF;
952     auto status = CheckAdvertisingDisableParams(env, info, advHandle);
953     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
954     auto func = [advHandle]() {
955         std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
956         if (bleAdvertiser == nullptr) {
957             HILOGE("bleAdvertiser is nullptr");
958             return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
959         }
960         int ret = bleAdvertiser->DisableAdvertising(
961             advHandle, NapiBluetoothBleAdvertiseCallback::GetInstance());
962         return NapiAsyncWorkRet(ret);
963     };
964 
965     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
966     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
967 
968     asyncWork->Run();
969     return asyncWork->GetRet();
970 }
971 #endif
972 
CheckStopAdvWithAdvId(napi_env env, napi_value object, uint32_t &outAdvHandle)973 napi_status CheckStopAdvWithAdvId(napi_env env, napi_value object, uint32_t &outAdvHandle)
974 {
975     NAPI_BT_CALL_RETURN(NapiParseUint32(env, object, outAdvHandle));
976 
977     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
978     NAPI_BT_RETURN_IF(bleAdvertiser == nullptr, "bleAdvertiser is nullptr", napi_invalid_arg);
979     if (outAdvHandle != bleAdvertiser->GetAdvHandle(NapiBluetoothBleAdvertiseCallback::GetInstance())) {
980         HILOGE("Invalid outAdvHandle: %{public}d", outAdvHandle);
981         return napi_invalid_arg;
982     }
983     return napi_ok;
984 }
985 
CheckEmptyArgs(napi_env env, napi_callback_info info)986 static napi_status CheckEmptyArgs(napi_env env, napi_callback_info info)
987 {
988     size_t argc = 0;
989     napi_value thisVar = nullptr;
990     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, nullptr, &thisVar, NULL));
991     NAPI_BT_RETURN_IF(argc > 0, "no needed arguments.", napi_invalid_arg);
992     return napi_ok;
993 }
994 
StopAdvertising(napi_env env, napi_callback_info info)995 napi_value StopAdvertising(napi_env env, napi_callback_info info)
996 {
997     HILOGD("enter");
998     size_t argc = ARGS_SIZE_TWO;
999     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
1000     napi_value thisVar = nullptr;
1001     auto checkRes = napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL);
1002     NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRes == napi_ok, BT_ERR_INVALID_PARAM);
1003 
1004     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
1005     NAPI_BT_ASSERT_RETURN_UNDEF(env, bleAdvertiser, BT_ERR_INTERNAL_ERROR);
1006 
1007     if (argc != ARGS_SIZE_ZERO) {
1008         auto status = napi_ok;
1009         if (argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO) {
1010             status = napi_invalid_arg;
1011         }
1012         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1013         uint32_t advHandle = 0xFF;
1014         status = CheckStopAdvWithAdvId(env, argv[PARAM0], advHandle);
1015         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1016         auto func = [bleAdvertiser]() {
1017             int ret = bleAdvertiser->StopAdvertising(
1018                 NapiBluetoothBleAdvertiseCallback::GetInstance());
1019             return NapiAsyncWorkRet(ret);
1020         };
1021 
1022         auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
1023         NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
1024 
1025         asyncWork->Run();
1026         return asyncWork->GetRet();
1027     } else {
1028         auto status = CheckEmptyArgs(env, info);
1029         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1030 
1031         int ret = bleAdvertiser->StopAdvertising(NapiBluetoothBleAdvertiseCallback::GetInstance());
1032         NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == BT_NO_ERROR, ret);
1033         return NapiGetUndefinedRet(env);
1034     }
1035 }
1036 
GetConnectedBLEDevices(napi_env env, napi_callback_info info)1037 napi_value GetConnectedBLEDevices(napi_env env, napi_callback_info info)
1038 {
1039     HILOGD("enter");
1040     napi_value result = nullptr;
1041     napi_create_array(env, &result);
1042 
1043     std::lock_guard<std::mutex> lock(NapiGattServer::deviceListMutex_);
1044     auto status = ConvertStringVectorToJS(env, result, NapiGattServer::deviceList_);
1045     NAPI_BT_ASSERT_RETURN(env, status == napi_ok, BT_ERR_INTERNAL_ERROR, result);
1046     return result;
1047 }
1048 
PropertyInit(napi_env env, napi_value exports)1049 napi_value PropertyInit(napi_env env, napi_value exports)
1050 {
1051     HILOGD("enter");
1052 
1053     napi_value matchModeObj = nullptr;
1054     napi_value scanDutyObj = nullptr;
1055     napi_value phyTypeObj = nullptr;
1056     napi_create_object(env, &matchModeObj);
1057     napi_create_object(env, &scanDutyObj);
1058     napi_create_object(env, &phyTypeObj);
1059 
1060     SetNamedPropertyByInteger(env, matchModeObj, MatchMode::MATCH_MODE_STICKY, "MATCH_MODE_STICKY");
1061     SetNamedPropertyByInteger(env, matchModeObj, MatchMode::MATCH_MODE_AGGRESSIVE, "MATCH_MODE_AGGRESSIVE");
1062     SetNamedPropertyByInteger(
1063         env, scanDutyObj, static_cast<int32_t>(ScanDuty::SCAN_MODE_BALANCED), "SCAN_MODE_BALANCED");
1064     SetNamedPropertyByInteger(
1065         env, scanDutyObj, static_cast<int32_t>(ScanDuty::SCAN_MODE_LOW_LATENCY), "SCAN_MODE_LOW_LATENCY");
1066     SetNamedPropertyByInteger(
1067         env, scanDutyObj, static_cast<int32_t>(ScanDuty::SCAN_MODE_LOW_POWER), "SCAN_MODE_LOW_POWER");
1068     SetNamedPropertyByInteger(
1069         env, phyTypeObj, static_cast<int32_t>(PhyType::PHY_LE_1M), "PHY_LE_1M");
1070     SetNamedPropertyByInteger(
1071         env, phyTypeObj, static_cast<int32_t>(PhyType::PHY_LE_ALL_SUPPORTED), "PHY_LE_ALL_SUPPORTED");
1072 
1073 #ifdef BLUETOOTH_API_SINCE_10
1074     napi_value gattWriteTypeObj = nullptr;
1075     napi_create_object(env, &gattWriteTypeObj);
1076     SetNamedPropertyByInteger(env, gattWriteTypeObj, static_cast<int32_t>(NapiGattWriteType::WRITE), "WRITE");
1077     SetNamedPropertyByInteger(
1078         env, gattWriteTypeObj, static_cast<int32_t>(NapiGattWriteType::WRITE_NO_RESPONSE), "WRITE_NO_RESPONSE");
1079 
1080     napi_value advertisingStateObj = nullptr;
1081     napi_create_object(env, &advertisingStateObj);
1082     SetNamedPropertyByInteger(env, advertisingStateObj, static_cast<int32_t>(AdvertisingState::STARTED), "STARTED");
1083     SetNamedPropertyByInteger(env, advertisingStateObj, static_cast<int32_t>(AdvertisingState::ENABLED), "ENABLED");
1084     SetNamedPropertyByInteger(env, advertisingStateObj, static_cast<int32_t>(AdvertisingState::DISABLED), "DISABLED");
1085     SetNamedPropertyByInteger(env, advertisingStateObj, static_cast<int32_t>(AdvertisingState::STOPPED), "STOPPED");
1086 #endif
1087 
1088     napi_property_descriptor exportFuncs[] = {
1089         DECLARE_NAPI_PROPERTY("MatchMode", matchModeObj),
1090         DECLARE_NAPI_PROPERTY("ScanDuty", scanDutyObj),
1091         DECLARE_NAPI_PROPERTY("PhyType", phyTypeObj),
1092 
1093 #ifdef BLUETOOTH_API_SINCE_10
1094         DECLARE_NAPI_PROPERTY("GattWriteType", gattWriteTypeObj),
1095         DECLARE_NAPI_PROPERTY("AdvertisingState", advertisingStateObj),
1096 #endif
1097     };
1098 
1099     HITRACE_METER_NAME(HITRACE_TAG_OHOS, "ble:napi_define_properties");
1100     napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
1101 
1102     return exports;
1103 }
1104 }  // namespace Bluetooth
1105 }  // namespace OHOS
1106