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