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