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