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