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