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, &paraType));
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 &params, 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 &params, 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 &params, 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 &params)
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> &params)
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