• 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 
ConvertScanReportMode(ScanOptions & params,int32_t scanReportMode)412 static void ConvertScanReportMode(ScanOptions &params, int32_t scanReportMode)
413 {
414     switch (scanReportMode) {
415         case static_cast<int32_t>(ScanReportMode::NORMAL):
416             params.reportMode = ScanReportMode::NORMAL;
417             break;
418         case static_cast<int32_t>(ScanReportMode::FENCE_SENSITIVITY_LOW):
419             params.reportMode = ScanReportMode::FENCE_SENSITIVITY_LOW;
420             break;
421         case static_cast<int32_t>(ScanReportMode::FENCE_SENSITIVITY_HIGH):
422             params.reportMode = ScanReportMode::FENCE_SENSITIVITY_HIGH;
423             break;
424         default:
425             break;
426     }
427 }
428 
ParseScanParameters(const napi_env & env,const napi_callback_info & info,const napi_value & scanArg,ScanOptions & params)429 static napi_status ParseScanParameters(
430     const napi_env &env, const napi_callback_info &info, const napi_value &scanArg, ScanOptions &params)
431 {
432     (void)info;
433     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(
434         env, scanArg, {"interval", "dutyMode", "matchMode", "phyType", "reportMode"}));
435 
436     bool exist = false;
437     int32_t interval = 0;
438     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "interval", exist, interval));
439     if (exist) {
440         HILOGI("Scan interval is %{public}d", interval);
441         params.interval = interval;
442     }
443 
444     int32_t dutyMode = 0;
445     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "dutyMode", exist, dutyMode));
446     if (exist) {
447         HILOGI("Scan dutyMode is %{public}d", dutyMode);
448         ConvertDutyMode(params, dutyMode);
449     }
450 
451     int32_t matchMode = 0;
452     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "matchMode", exist, matchMode));
453     if (exist) {
454         HILOGI("Scan matchMode is %{public}d", matchMode);
455         ConvertMatchMode(params, matchMode);
456     }
457 
458     int32_t phyType = 0;
459     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "phyType", exist, phyType));
460     if (exist) {
461         HILOGI("Scan phyType is %{public}d", phyType);
462         ConvertPhyType(params, phyType);
463     }
464     // This parameter is overwritten by the value entered by the user.
465     int32_t scanReportMode = 0;
466     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "reportMode", exist, scanReportMode));
467     if (exist) {
468         HILOGI("Scan reportMode is %{public}d", scanReportMode);
469         // Default value of params is ScanReportMode::NORMAL.
470         ConvertScanReportMode(params, scanReportMode);
471     }
472     return napi_ok;
473 }
474 
ParseScanFilterDeviceIdParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)475 static napi_status ParseScanFilterDeviceIdParameters(
476     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
477 {
478     bool exist = false;
479     std::string deviceId {};
480     NAPI_BT_CALL_RETURN(ParseStringParams(env, scanFilter, "deviceId", exist, deviceId));
481     if (exist) {
482         if (!IsValidAddress(deviceId)) {
483             HILOGE("Invalid deviceId: %{public}s", deviceId.c_str());
484             return napi_invalid_arg;
485         }
486 
487         HILOGI("Scan filter device id is %{public}s", GetEncryptAddr(deviceId).c_str());
488         bleScanFilter.SetDeviceId(deviceId);
489     }
490     return napi_ok;
491 }
492 
ParseScanFilterLocalNameParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)493 static napi_status ParseScanFilterLocalNameParameters(
494     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
495 {
496     bool exist = false;
497     std::string name {};
498     NAPI_BT_CALL_RETURN(ParseStringParams(env, scanFilter, "name", exist, name));
499     if (exist) {
500         if (name.empty()) {
501             HILOGE("name is empty");
502             return napi_invalid_arg;
503         }
504         HILOGI("Scan filter name is %{public}s", name.c_str());
505         bleScanFilter.SetName(name);
506     }
507     return napi_ok;
508 }
509 
ParseScanFilterServiceUuidParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)510 static napi_status ParseScanFilterServiceUuidParameters(
511     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
512 {
513     bool exist = false;
514     UUID uuid {};
515     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceUuid", exist, uuid));
516     if (exist) {
517         HILOGI("Scan filter serviceUuid is %{public}s", uuid.ToString().c_str());
518         bleScanFilter.SetServiceUuid(uuid);
519     }
520 
521     UUID uuidMask {};
522     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceUuidMask", exist, uuidMask));
523     if (exist) {
524         HILOGI("Scan filter serviceUuidMask is %{public}s", uuidMask.ToString().c_str());
525         bleScanFilter.SetServiceUuidMask(uuidMask);
526     }
527     return napi_ok;
528 }
529 
ParseScanFilterSolicitationUuidParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)530 static napi_status ParseScanFilterSolicitationUuidParameters(
531     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
532 {
533     bool exist = false;
534     UUID uuid {};
535     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceSolicitationUuid", exist, uuid));
536     if (exist) {
537         HILOGI("Scan filter serviceSolicitationUuid is %{public}s", uuid.ToString().c_str());
538         bleScanFilter.SetServiceSolicitationUuid(uuid);
539     }
540 
541     UUID uuidMask {};
542     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceSolicitationUuidMask", exist, uuidMask));
543     if (exist) {
544         HILOGI("Scan filter serviceSolicitationUuidMask is %{public}s", uuidMask.ToString().c_str());
545         bleScanFilter.SetServiceSolicitationUuidMask(uuidMask);
546     }
547     return napi_ok;
548 }
549 
ParseScanFilterServiceDataParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)550 static napi_status ParseScanFilterServiceDataParameters(
551     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
552 {
553     bool exist = false;
554     std::vector<uint8_t> data {};
555     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "serviceData", exist, data));
556     if (exist) {
557         bleScanFilter.SetServiceData(std::move(data));
558     }
559 
560     std::vector<uint8_t> dataMask {};
561     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "serviceDataMask", exist, dataMask));
562     if (exist) {
563         bleScanFilter.SetServiceDataMask(std::move(dataMask));
564     }
565     return napi_ok;
566 }
567 
ParseScanFilterManufactureDataParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)568 static napi_status ParseScanFilterManufactureDataParameters(
569     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
570 {
571     bool exist = false;
572     napi_value result;
573     NAPI_BT_CALL_RETURN(ParseNumberParams(env, scanFilter, "manufactureId", exist, result));
574     if (exist) {
575         uint32_t manufacturerId = 0;
576         NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, result, &manufacturerId));
577         bleScanFilter.SetManufacturerId(manufacturerId);
578         HILOGI("Scan filter manufacturerId is %{public}#x", manufacturerId);
579     }
580 
581     exist = false;
582     std::vector<uint8_t> data {};
583     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "manufactureData", exist, data));
584     if (exist) {
585         bleScanFilter.SetManufactureData(std::move(data));
586     }
587 
588     std::vector<uint8_t> dataMask {};
589     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "manufactureDataMask", exist, dataMask));
590     if (exist) {
591         bleScanFilter.SetManufactureDataMask(std::move(dataMask));
592     }
593     return napi_ok;
594 }
595 
ParseScanFilter(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)596 static napi_status ParseScanFilter(const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
597 {
598     HILOGD("enter");
599     std::vector<std::string> expectedNames {"deviceId", "name", "serviceUuid", "serviceUuidMask",
600         "serviceSolicitationUuid", "serviceSolicitationUuidMask", "serviceData", "serviceDataMask", "manufactureId",
601         "manufactureData", "manufactureDataMask"};
602     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, scanFilter, expectedNames));
603 
604     NAPI_BT_CALL_RETURN(ParseScanFilterDeviceIdParameters(env, scanFilter, bleScanFilter));
605     NAPI_BT_CALL_RETURN(ParseScanFilterLocalNameParameters(env, scanFilter, bleScanFilter));
606     NAPI_BT_CALL_RETURN(ParseScanFilterServiceUuidParameters(env, scanFilter, bleScanFilter));
607     NAPI_BT_CALL_RETURN(ParseScanFilterSolicitationUuidParameters(env, scanFilter, bleScanFilter));
608     NAPI_BT_CALL_RETURN(ParseScanFilterServiceDataParameters(env, scanFilter, bleScanFilter));
609     NAPI_BT_CALL_RETURN(ParseScanFilterManufactureDataParameters(env, scanFilter, bleScanFilter));
610     return napi_ok;
611 }
612 
ParseScanFilterParameters(const napi_env & env,napi_value & args,std::vector<BleScanFilter> & params)613 static napi_status ParseScanFilterParameters(const napi_env &env, napi_value &args, std::vector<BleScanFilter> &params)
614 {
615     HILOGD("enter");
616     NAPI_BT_CALL_RETURN(NapiIsArray(env, args));
617 
618     uint32_t length = 0;
619     NAPI_BT_CALL_RETURN(napi_get_array_length(env, args, &length));
620     NAPI_BT_RETURN_IF(length == 0, "Requires array length > 0", napi_invalid_arg);
621     for (uint32_t i = 0; i < length; i++) {
622         napi_value scanFilter;
623         NAPI_BT_CALL_RETURN(napi_get_element(env, args, i, &scanFilter));
624         NAPI_BT_CALL_RETURN(NapiIsObject(env, scanFilter));
625         BleScanFilter bleScanFilter;
626         NAPI_BT_CALL_RETURN(ParseScanFilter(env, scanFilter, bleScanFilter));
627         params.push_back(bleScanFilter);
628     }
629     return napi_ok;
630 }
631 
CheckBleScanParams(napi_env env,napi_callback_info info,std::vector<BleScanFilter> & outScanfilters,BleScanSettings & outSettinngs)632 napi_status CheckBleScanParams(napi_env env, napi_callback_info info, std::vector<BleScanFilter> &outScanfilters,
633     BleScanSettings &outSettinngs)
634 {
635     size_t argc = ARGS_SIZE_TWO;
636     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
637     napi_value thisVar = nullptr;
638     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
639     NAPI_BT_RETURN_IF((argc == 0 || argc > ARGS_SIZE_TWO), "Requires 1 or 2 arguments.", napi_invalid_arg);
640 
641     std::vector<BleScanFilter> scanfilters;
642     // Support null param
643     napi_valuetype type = napi_undefined;
644     NAPI_BT_CALL_RETURN(napi_typeof(env, argv[PARAM0], &type));
645     if (type == napi_null) {
646         BleScanFilter emptyFilter;
647         scanfilters.push_back(emptyFilter);
648     } else {
649         NAPI_BT_CALL_RETURN(ParseScanFilterParameters(env, argv[PARAM0], scanfilters));
650     }
651 
652     if (argc == ARGS_SIZE_TWO) {
653         ScanOptions scanOptions;
654         NAPI_BT_CALL_RETURN(ParseScanParameters(env, info, argv[PARAM1], scanOptions));
655         outSettinngs.SetReportDelay(scanOptions.interval);
656         outSettinngs.SetScanMode(static_cast<int32_t>(scanOptions.dutyMode));
657         outSettinngs.SetPhy(static_cast<int32_t>(scanOptions.phyType));
658         // reportMode -> callbackType + sensitivityMode
659         uint8_t callbackType = BLE_SCAN_CALLBACK_TYPE_ALL_MATCH;
660         uint8_t sensitivityMode = static_cast<uint8_t>(SensitivityMode::SENSITIVITY_MODE_HIGH);
661         switch (scanOptions.reportMode) {
662             case ScanReportMode::NORMAL:
663                 callbackType = BLE_SCAN_CALLBACK_TYPE_ALL_MATCH;
664                 break;
665             case ScanReportMode::FENCE_SENSITIVITY_LOW:
666                 callbackType = BLE_SCAN_CALLBACK_TYPE_FIRST_AND_LOST_MATCH;
667                 sensitivityMode = static_cast<uint8_t>(SensitivityMode::SENSITIVITY_MODE_LOW);
668                 break;
669             case ScanReportMode::FENCE_SENSITIVITY_HIGH:
670                 callbackType = BLE_SCAN_CALLBACK_TYPE_FIRST_AND_LOST_MATCH;
671                 sensitivityMode = static_cast<uint8_t>(SensitivityMode::SENSITIVITY_MODE_HIGH);
672                 break;
673             default:
674                 break;
675         }
676         outSettinngs.SetCallbackType(callbackType);
677         outSettinngs.SetSensitivityMode(sensitivityMode);
678     }
679 
680     outScanfilters = std::move(scanfilters);
681     return napi_ok;
682 }
683 
StartBLEScan(napi_env env,napi_callback_info info)684 napi_value StartBLEScan(napi_env env, napi_callback_info info)
685 {
686     HILOGD("enter");
687     std::vector<BleScanFilter> scanfilters;
688     BleScanSettings settings;
689     auto status = CheckBleScanParams(env, info, scanfilters, settings);
690     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
691 
692     int ret = BleCentralManagerGetInstance()->StartScan(settings, scanfilters);
693     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == NO_ERROR || ret == BT_ERR_BLE_SCAN_ALREADY_STARTED, ret);
694 
695     return NapiGetUndefinedRet(env);
696 }
697 
StopBLEScan(napi_env env,napi_callback_info info)698 napi_value StopBLEScan(napi_env env, napi_callback_info info)
699 {
700     HILOGD("enter");
701     auto status = CheckEmptyParam(env, info);
702     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
703 
704     int ret = BleCentralManagerGetInstance()->StopScan();
705     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == NO_ERROR, ret);
706     return NapiGetUndefinedRet(env);
707 }
708 
ParseAdvertisingSettingsParameters(const napi_env & env,const napi_value & object,BleAdvertiserSettings & outSettings)709 static napi_status ParseAdvertisingSettingsParameters(
710     const napi_env &env, const napi_value &object, BleAdvertiserSettings &outSettings)
711 {
712     HILOGD("enter");
713     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"interval", "txPower", "connectable"}));
714 
715     bool exist = false;
716     uint32_t interval = 0;
717     NAPI_BT_CALL_RETURN(NapiParseObjectUint32Optional(env, object, "interval", interval, exist));
718     if (exist) {
719         const uint32_t minInterval = 32;
720         const uint32_t maxInterval = 16384;
721         if (interval < minInterval || interval > maxInterval) {
722             HILOGE("Invalid interval: %{public}d", interval);
723             return napi_invalid_arg;
724         }
725         HILOGI("interval: %{public}u", interval);
726         outSettings.SetInterval(interval);
727     }
728 
729     int32_t txPower = -7; // default txPower value
730     NAPI_BT_CALL_RETURN(NapiParseObjectInt32Optional(env, object, "txPower", txPower, exist));
731     if (exist) {
732         const int32_t minTxPower = -127;
733         const int32_t maxTxPower = 1;
734         if (txPower < minTxPower || txPower > maxTxPower) {
735             HILOGE("Invalid tx power: %{public}d", txPower);
736             return napi_invalid_arg;
737         }
738         HILOGI("txPower is %{public}d", txPower);
739         outSettings.SetTxPower(txPower);
740     }
741 
742     bool connectable = false;
743     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(env, object, "connectable", connectable, exist));
744     if (exist) {
745         HILOGI("connectable: %{public}d", connectable);
746         outSettings.SetConnectable(connectable);
747     }
748     return napi_ok;
749 }
750 
ParseServiceUuidParameters(napi_env env,napi_value object,BleAdvertiserData & outData)751 static napi_status ParseServiceUuidParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
752 {
753     HILOGD("enter");
754     std::vector<UUID> vec {};
755     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "serviceUuids", vec));
756     for (size_t i = 0; i < vec.size(); ++i) {
757         outData.AddServiceUuid(vec[i]);
758         HILOGI("Service Uuid = %{public}s", vec[i].ToString().c_str());
759     }
760     return napi_ok;
761 }
762 
ParseManufactureDataParameters(napi_env env,napi_value object,BleAdvertiserData & outData)763 static napi_status ParseManufactureDataParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
764 {
765     HILOGD("enter");
766     std::vector<NapiAdvManufactureData> vec {};
767     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "manufactureData", vec));
768     for (size_t i = 0; i < vec.size(); ++i) {
769         outData.AddManufacturerData(vec[i].id, vec[i].value);
770     }
771     return napi_ok;
772 }
773 
ParseServiceDataParameters(napi_env env,napi_value object,BleAdvertiserData & outData)774 static napi_status ParseServiceDataParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
775 {
776     HILOGD("enter");
777     std::vector<NapiAdvServiceData> vec {};
778     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "serviceData", vec));
779     for (size_t i = 0; i < vec.size(); ++i) {
780         outData.AddServiceData(
781             ParcelUuid::FromString(vec[i].uuid),
782             std::string(vec[i].value.begin(), vec[i].value.end()));
783     }
784     return napi_ok;
785 }
786 
ParseAdvertisDataParameters(const napi_env & env,const napi_value & object,BleAdvertiserData & outData)787 static napi_status ParseAdvertisDataParameters(const napi_env &env,
788     const napi_value &object, BleAdvertiserData &outData)
789 {
790     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(
791         env, object, {"serviceUuids", "manufactureData", "serviceData", "includeDeviceName", "includeTxPower"}));
792 
793     NAPI_BT_CALL_RETURN(ParseServiceUuidParameters(env, object, outData));
794     NAPI_BT_CALL_RETURN(ParseManufactureDataParameters(env, object, outData));
795     NAPI_BT_CALL_RETURN(ParseServiceDataParameters(env, object, outData));
796     bool exist = false;
797     bool includeDeviceName = false;
798     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(env, object, "includeDeviceName", includeDeviceName, exist));
799     HILOGI("includeDeviceName: %{public}d", includeDeviceName);
800     outData.SetIncludeDeviceName(includeDeviceName);
801 
802     bool includeTxPower = false;
803     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(env, object, "includeTxPower", includeTxPower, exist));
804     HILOGI("includeTxPower: %{public}d", includeTxPower);
805     outData.SetIncludeTxPower(includeTxPower);
806 
807     return napi_ok;
808 }
809 
IsValidAdvertiserDuration(uint32_t duration)810 static bool IsValidAdvertiserDuration(uint32_t duration)
811 {
812     const uint32_t MIN_DURATION = 0;
813     const uint32_t MAX_DURATION = 65535;
814     if (duration < MIN_DURATION || duration > MAX_DURATION) {
815         return false;
816     }
817     return true;
818 }
819 
CheckAdvertisingDataWithDuration(napi_env env,napi_value object,BleAdvertiserSettings & outSettings,BleAdvertiserData & outAdvData,BleAdvertiserData & outRspData,uint16_t & outDuration)820 napi_status CheckAdvertisingDataWithDuration(napi_env env, napi_value object, BleAdvertiserSettings &outSettings,
821     BleAdvertiserData &outAdvData, BleAdvertiserData &outRspData, uint16_t &outDuration)
822 {
823     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"advertisingSettings", "advertisingData",
824         "advertisingResponse", "duration"}));
825 
826     napi_value advSettingsObject;
827     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
828     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, "advertisingSettings", advSettingsObject));
829     BleAdvertiserSettings settings;
830     NAPI_BT_CALL_RETURN(ParseAdvertisingSettingsParameters(env, advSettingsObject, settings));
831 
832     napi_value advDataObject;
833     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, "advertisingData", advDataObject));
834     BleAdvertiserData advData;
835     NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, advDataObject, advData));
836 
837     BleAdvertiserData advRsp;
838     if (NapiIsObjectPropertyExist(env, object, "advertisingResponse")) {
839         napi_value advRspObject;
840         NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, "advertisingResponse", advRspObject));
841         NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, advRspObject, advRsp));
842     }
843 
844     bool exist = false;
845     uint32_t duration = 0;
846     NAPI_BT_CALL_RETURN(NapiParseObjectUint32Optional(env, object, "duration", duration, exist));
847     if (exist) {
848         if (!IsValidAdvertiserDuration(duration)) {
849             HILOGE("Invalid duration: %{public}d", duration);
850             return napi_invalid_arg;
851         }
852         HILOGI("duration: %{public}u", duration);
853     }
854     outDuration = duration;
855     outSettings = std::move(settings);
856     outAdvData = std::move(advData);
857     outRspData = std::move(advRsp);
858     return napi_ok;
859 }
860 
CheckAdvertisingData(napi_env env,napi_callback_info info,BleAdvertiserSettings & outSettings,BleAdvertiserData & outAdvData,BleAdvertiserData & outRspData)861 napi_status CheckAdvertisingData(napi_env env, napi_callback_info info, BleAdvertiserSettings &outSettings,
862     BleAdvertiserData &outAdvData, BleAdvertiserData &outRspData)
863 {
864     size_t argc = ARGS_SIZE_THREE;
865     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
866     napi_value thisVar = nullptr;
867     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
868     NAPI_BT_RETURN_IF((argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE), "need 2 or 3 arguments.", napi_invalid_arg);
869 
870     BleAdvertiserSettings settings;
871     NAPI_BT_CALL_RETURN(ParseAdvertisingSettingsParameters(env, argv[PARAM0], settings));
872     BleAdvertiserData advData;
873     NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, argv[PARAM1], advData));
874     BleAdvertiserData rspData;
875     if (argc == ARGS_SIZE_THREE) {
876         NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, argv[PARAM2], rspData));
877     }
878 
879     outSettings = std::move(settings);
880     outAdvData = std::move(advData);
881     outRspData = std::move(rspData);
882     return napi_ok;
883 }
884 
StartAdvertising(napi_env env,napi_callback_info info)885 napi_value StartAdvertising(napi_env env, napi_callback_info info)
886 {
887     HILOGI("enter");
888     size_t argc = ARGS_SIZE_THREE;
889     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
890     napi_value thisVar = nullptr;
891     auto checkRes = napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL);
892     NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRes == napi_ok, BT_ERR_INVALID_PARAM);
893 
894     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
895     NAPI_BT_ASSERT_RETURN_UNDEF(env, bleAdvertiser, BT_ERR_INTERNAL_ERROR);
896 
897     BleAdvertiserSettings settings;
898     BleAdvertiserData advData;
899     BleAdvertiserData rspData;
900     if (argc != 0 && NapiIsObjectPropertyExist(env, argv[PARAM0], "advertisingSettings")) {
901         uint16_t duration = 0;
902         auto status = CheckAdvertisingDataWithDuration(env, argv[PARAM0], settings, advData, rspData, duration);
903         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
904         auto callback = std::make_shared<NapiBluetoothBleAdvertiseCallback>();
905         auto func = [settings, advData, rspData, duration, bleAdvertiser, callback]() {
906             int ret = bleAdvertiser->StartAdvertising(
907                 settings, advData, rspData, duration, callback);
908             return NapiAsyncWorkRet(ret);
909         };
910 
911         auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
912         NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
913         bool success = callback->asyncWorkMap_.TryPush(
914             NapiAsyncType::GET_ADVERTISING_HANDLE, asyncWork);
915         NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
916 
917         asyncWork->Run();
918         return asyncWork->GetRet();
919     } else {
920         auto status = CheckAdvertisingData(env, info, settings, advData, rspData);
921         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
922         int ret = bleAdvertiser->StartAdvertising(
923             settings, advData, rspData, 0, NapiBluetoothBleAdvertiseCallback::GetInstance());
924         NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == BT_NO_ERROR, ret);
925         return NapiGetUndefinedRet(env);
926     }
927 }
928 
929 #ifdef BLUETOOTH_API_SINCE_10
CheckAdvertisingEnableParams(napi_env env,napi_callback_info info,uint32_t & outAdvHandle,uint16_t & outDuration,std::shared_ptr<BleAdvertiseCallback> & callback)930 napi_status CheckAdvertisingEnableParams(napi_env env, napi_callback_info info,
931     uint32_t &outAdvHandle, uint16_t &outDuration, std::shared_ptr<BleAdvertiseCallback> &callback)
932 {
933     size_t argc = ARGS_SIZE_TWO;
934     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
935     napi_value thisVar = nullptr;
936     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
937     NAPI_BT_RETURN_IF((argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO), "need 1 or 2 arguments.", napi_invalid_arg);
938 
939     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, argv[PARAM0], {"advertisingId", "duration"}));
940     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, argv[PARAM0], "advertisingId", outAdvHandle));
941 
942     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
943     NAPI_BT_RETURN_IF(bleAdvertiser == nullptr, "bleAdvertiser is nullptr", napi_invalid_arg);
944     if (outAdvHandle != BLE_INVALID_ADVERTISING_HANDLE) {
945         callback = bleAdvertiser->GetAdvObserver(outAdvHandle);
946         NAPI_BT_RETURN_IF(callback == nullptr, "callback is nullptr", napi_invalid_arg);
947     }
948 
949     bool exist = false;
950     uint32_t duration = 0;
951     NAPI_BT_CALL_RETURN(NapiParseObjectUint32Optional(env, argv[PARAM0], "duration", duration, exist));
952     if (exist) {
953         if (!IsValidAdvertiserDuration(duration)) {
954             HILOGE("Invalid duration: %{public}d", duration);
955             return napi_invalid_arg;
956         }
957         HILOGI("duration: %{public}u", duration);
958     }
959     outDuration = duration;
960 
961     return napi_ok;
962 }
963 
EnableAdvertising(napi_env env,napi_callback_info info)964 napi_value EnableAdvertising(napi_env env, napi_callback_info info)
965 {
966     HILOGI("enter");
967     uint32_t advHandle = 0xFF;
968     uint16_t duration = 0;
969     std::shared_ptr<BleAdvertiseCallback> baseCallback;
970     auto status = CheckAdvertisingEnableParams(env, info, advHandle, duration, baseCallback);
971     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
972     // compatible with XTS
973     NAPI_BT_ASSERT_RETURN_UNDEF(env, advHandle != BLE_INVALID_ADVERTISING_HANDLE, BT_ERR_INTERNAL_ERROR);
974     std::shared_ptr<NapiBluetoothBleAdvertiseCallback> callback =
975         std::static_pointer_cast<NapiBluetoothBleAdvertiseCallback>(baseCallback);
976     auto func = [advHandle, duration, callback]() {
977         std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
978         if (bleAdvertiser == nullptr) {
979             HILOGE("bleAdvertiser is nullptr");
980             return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
981         }
982         int ret = bleAdvertiser->EnableAdvertising(
983             advHandle, duration, callback);
984         return NapiAsyncWorkRet(ret);
985     };
986 
987     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
988     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
989     bool success = callback->asyncWorkMap_.TryPush(
990         NapiAsyncType::BLE_ENABLE_ADVERTISING, asyncWork);
991     NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
992 
993     asyncWork->Run();
994     return asyncWork->GetRet();
995 }
996 
CheckAdvertisingDisableParams(napi_env env,napi_callback_info info,uint32_t & outAdvHandle,std::shared_ptr<BleAdvertiseCallback> & callback)997 napi_status CheckAdvertisingDisableParams(napi_env env, napi_callback_info info, uint32_t &outAdvHandle,
998     std::shared_ptr<BleAdvertiseCallback> &callback)
999 {
1000     size_t argc = ARGS_SIZE_TWO;
1001     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
1002     napi_value thisVar = nullptr;
1003     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
1004     NAPI_BT_RETURN_IF((argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO), "need 1 or 2 arguments.", napi_invalid_arg);
1005 
1006     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, argv[PARAM0], {"advertisingId"}));
1007     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, argv[PARAM0], "advertisingId", outAdvHandle));
1008 
1009     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
1010     NAPI_BT_RETURN_IF(bleAdvertiser == nullptr, "bleAdvertiser is nullptr", napi_invalid_arg);
1011     if (outAdvHandle != BLE_INVALID_ADVERTISING_HANDLE) {
1012         callback = bleAdvertiser->GetAdvObserver(outAdvHandle);
1013         NAPI_BT_RETURN_IF(callback == nullptr, "callback is nullptr", napi_invalid_arg);
1014     }
1015 
1016     return napi_ok;
1017 }
1018 
DisableAdvertising(napi_env env,napi_callback_info info)1019 napi_value DisableAdvertising(napi_env env, napi_callback_info info)
1020 {
1021     HILOGI("enter");
1022     uint32_t advHandle = 0xFF;
1023     std::shared_ptr<BleAdvertiseCallback> baseCallback;
1024     auto status = CheckAdvertisingDisableParams(env, info, advHandle, baseCallback);
1025     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1026     // compatible with XTS
1027     NAPI_BT_ASSERT_RETURN_UNDEF(env, advHandle != BLE_INVALID_ADVERTISING_HANDLE, BT_ERR_INTERNAL_ERROR);
1028     std::shared_ptr<NapiBluetoothBleAdvertiseCallback> callback =
1029         std::static_pointer_cast<NapiBluetoothBleAdvertiseCallback>(baseCallback);
1030     auto func = [advHandle, callback]() {
1031         std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
1032         if (bleAdvertiser == nullptr) {
1033             HILOGE("bleAdvertiser is nullptr");
1034             return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
1035         }
1036         int ret = bleAdvertiser->DisableAdvertising(
1037             advHandle, callback);
1038         return NapiAsyncWorkRet(ret);
1039     };
1040 
1041     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
1042     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
1043     bool success = callback->asyncWorkMap_.TryPush(
1044         NapiAsyncType::BLE_DISABLE_ADVERTISING, asyncWork);
1045     NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
1046 
1047     asyncWork->Run();
1048     return asyncWork->GetRet();
1049 }
1050 #endif
1051 
CheckStopAdvWithAdvId(napi_env env,napi_value object,uint32_t & outAdvHandle,std::shared_ptr<BleAdvertiseCallback> & callback)1052 napi_status CheckStopAdvWithAdvId(napi_env env, napi_value object, uint32_t &outAdvHandle,
1053     std::shared_ptr<BleAdvertiseCallback> &callback)
1054 {
1055     NAPI_BT_CALL_RETURN(NapiParseUint32(env, object, outAdvHandle));
1056 
1057     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
1058     NAPI_BT_RETURN_IF(bleAdvertiser == nullptr, "bleAdvertiser is nullptr", napi_invalid_arg);
1059     if (outAdvHandle != BLE_INVALID_ADVERTISING_HANDLE) {
1060         callback = bleAdvertiser->GetAdvObserver(outAdvHandle);
1061         NAPI_BT_RETURN_IF(callback == nullptr, "callback is nullptr", napi_invalid_arg);
1062     }
1063     return napi_ok;
1064 }
1065 
CheckEmptyArgs(napi_env env,napi_callback_info info)1066 static napi_status CheckEmptyArgs(napi_env env, napi_callback_info info)
1067 {
1068     size_t argc = 0;
1069     napi_value thisVar = nullptr;
1070     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, nullptr, &thisVar, NULL));
1071     NAPI_BT_RETURN_IF(argc > 0, "no needed arguments.", napi_invalid_arg);
1072     return napi_ok;
1073 }
1074 
StopAdvertising(napi_env env,napi_callback_info info)1075 napi_value StopAdvertising(napi_env env, napi_callback_info info)
1076 {
1077     HILOGD("enter");
1078     size_t argc = ARGS_SIZE_TWO;
1079     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
1080     napi_value thisVar = nullptr;
1081     auto checkRes = napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL);
1082     NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRes == napi_ok, BT_ERR_INVALID_PARAM);
1083 
1084     std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
1085     NAPI_BT_ASSERT_RETURN_UNDEF(env, bleAdvertiser, BT_ERR_INTERNAL_ERROR);
1086 
1087     if (argc != ARGS_SIZE_ZERO) {
1088         auto status = napi_ok;
1089         if (argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO) {
1090             status = napi_invalid_arg;
1091         }
1092         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1093         uint32_t advHandle = 0xFF;
1094         std::shared_ptr<BleAdvertiseCallback> baseCallback;
1095         status = CheckStopAdvWithAdvId(env, argv[PARAM0], advHandle, baseCallback);
1096         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1097         // compatible with XTS
1098         NAPI_BT_ASSERT_RETURN_UNDEF(env, advHandle != BLE_INVALID_ADVERTISING_HANDLE, BT_ERR_INTERNAL_ERROR);
1099         std::shared_ptr<NapiBluetoothBleAdvertiseCallback> callback =
1100             std::static_pointer_cast<NapiBluetoothBleAdvertiseCallback>(baseCallback);
1101         auto func = [bleAdvertiser, callback]() {
1102             int ret = bleAdvertiser->StopAdvertising(callback);
1103             return NapiAsyncWorkRet(ret);
1104         };
1105 
1106         auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
1107         NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
1108         bool success = callback->asyncWorkMap_.TryPush(
1109             NapiAsyncType::BLE_STOP_ADVERTISING, asyncWork);
1110         NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
1111 
1112         asyncWork->Run();
1113         return asyncWork->GetRet();
1114     } else {
1115         auto status = CheckEmptyArgs(env, info);
1116         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1117         std::vector<std::shared_ptr<BleAdvertiseCallback>> callbacks = bleAdvertiser->GetAdvObservers();
1118         if (callbacks.empty()) {
1119             // compatible with XTS
1120             int ret = bleAdvertiser->StopAdvertising(NapiBluetoothBleAdvertiseCallback::GetInstance());
1121             NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == BT_NO_ERROR, ret);
1122         } else {
1123             for (auto &callback : callbacks) {
1124                 int ret = bleAdvertiser->StopAdvertising(callback);
1125                 NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == BT_NO_ERROR, ret);
1126             }
1127         }
1128         return NapiGetUndefinedRet(env);
1129     }
1130 }
1131 
GetConnectedBLEDevices(napi_env env,napi_callback_info info)1132 napi_value GetConnectedBLEDevices(napi_env env, napi_callback_info info)
1133 {
1134     HILOGD("enter");
1135     napi_value result = nullptr;
1136     napi_create_array(env, &result);
1137 
1138     std::lock_guard<std::mutex> lock(NapiGattServer::deviceListMutex_);
1139     auto status = ConvertStringVectorToJS(env, result, NapiGattServer::deviceList_);
1140     NAPI_BT_ASSERT_RETURN(env, status == napi_ok, BT_ERR_INTERNAL_ERROR, result);
1141     return result;
1142 }
1143 
PropertyInit(napi_env env,napi_value exports)1144 napi_value PropertyInit(napi_env env, napi_value exports)
1145 {
1146     HILOGD("enter");
1147     napi_value matchModeObj = MatchModeInit(env);
1148     napi_value scanDutyObj = ScanDutyInit(env);
1149     napi_value phyTypeObj = PhyTypeInit(env);
1150     napi_value reportModeObj = ScanReportModeInit(env);
1151 
1152 #ifdef BLUETOOTH_API_SINCE_10
1153     napi_value gattWriteTypeObj = nullptr;
1154     napi_create_object(env, &gattWriteTypeObj);
1155     SetNamedPropertyByInteger(env, gattWriteTypeObj, static_cast<int32_t>(NapiGattWriteType::WRITE), "WRITE");
1156     SetNamedPropertyByInteger(
1157         env, gattWriteTypeObj, static_cast<int32_t>(NapiGattWriteType::WRITE_NO_RESPONSE), "WRITE_NO_RESPONSE");
1158 
1159     napi_value advertisingStateObj = nullptr;
1160     napi_create_object(env, &advertisingStateObj);
1161     SetNamedPropertyByInteger(env, advertisingStateObj, static_cast<int32_t>(AdvertisingState::STARTED), "STARTED");
1162     SetNamedPropertyByInteger(env, advertisingStateObj, static_cast<int32_t>(AdvertisingState::ENABLED), "ENABLED");
1163     SetNamedPropertyByInteger(env, advertisingStateObj, static_cast<int32_t>(AdvertisingState::DISABLED), "DISABLED");
1164     SetNamedPropertyByInteger(env, advertisingStateObj, static_cast<int32_t>(AdvertisingState::STOPPED), "STOPPED");
1165 
1166     napi_value scanReportTypeObj = ScanReportTypeInit(env);
1167 #endif
1168 
1169     napi_property_descriptor exportFuncs[] = {
1170         DECLARE_NAPI_PROPERTY("MatchMode", matchModeObj),
1171         DECLARE_NAPI_PROPERTY("ScanDuty", scanDutyObj),
1172         DECLARE_NAPI_PROPERTY("PhyType", phyTypeObj),
1173         DECLARE_NAPI_PROPERTY("ScanReportMode", reportModeObj),
1174 
1175 #ifdef BLUETOOTH_API_SINCE_10
1176         DECLARE_NAPI_PROPERTY("GattWriteType", gattWriteTypeObj),
1177         DECLARE_NAPI_PROPERTY("AdvertisingState", advertisingStateObj),
1178         DECLARE_NAPI_PROPERTY("ScanReportType", scanReportTypeObj),
1179 #endif
1180     };
1181 
1182     HITRACE_METER_NAME(HITRACE_TAG_OHOS, "ble:napi_define_properties");
1183     napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
1184 
1185     return exports;
1186 }
1187 }  // namespace Bluetooth
1188 }  // namespace OHOS
1189