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, ¶Type));
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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms)
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> ¶ms)
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