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