1 /*
2  * Copyright (C) 2021-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 
16 #include "napi_bluetooth_utils.h"
17 #include <algorithm>
18 #include <functional>
19 #include <optional>
20 #include "bluetooth_log.h"
21 #include "bluetooth_utils.h"
22 #include "event_handler.h"  // libeventhandler
23 #include "event_runner.h"  // libeventhandler
24 #include "napi/native_api.h"
25 #include "napi/native_node_api.h"
26 #include "napi_bluetooth_error.h"
27 #include "napi_bluetooth_spp_client.h"
28 #include "../parser/napi_parser_utils.h"
29 #include "securec.h"
30 
31 namespace OHOS {
32 namespace Bluetooth {
33 using namespace std;
34 
GetCallbackErrorValue(napi_env env, int errCode)35 napi_value GetCallbackErrorValue(napi_env env, int errCode)
36 {
37     HILOGE("errCode: %{public}d", errCode);
38     napi_value result = NapiGetNull(env);
39     napi_value eCode = NapiGetNull(env);
40     if (errCode == BT_NO_ERROR) {
41         return result;
42     }
43     NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
44     NAPI_CALL(env, napi_create_object(env, &result));
45     NAPI_CALL(env, napi_set_named_property(env, result, "code", eCode));
46 
47     std::string errMsg = GetNapiErrMsg(env, errCode);
48     napi_value message = nullptr;
49     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
50     napi_set_named_property(env, result, "message", message);
51     return result;
52 }
53 
GetCallbackInfoByType(const std::string &type)54 std::shared_ptr<BluetoothCallbackInfo> GetCallbackInfoByType(const std::string &type)
55 {
56     std::lock_guard<std::mutex> lock(g_observerMutex);
57     std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> observers = GetObserver();
58     if (!observers[type]) {
59         return nullptr;
60     }
61     return observers[type];
62 }
63 
ParseString(napi_env env, string &param, napi_value args)64 bool ParseString(napi_env env, string &param, napi_value args)
65 {
66     napi_valuetype valuetype;
67     napi_typeof(env, args, &valuetype);
68 
69     if (valuetype != napi_string) {
70         HILOGE("Wrong argument type(%{public}d). String expected.", valuetype);
71         return false;
72     }
73     size_t size = 0;
74 
75     if (napi_get_value_string_utf8(env, args, nullptr, 0, &size) != napi_ok) {
76         HILOGE("can not get string size");
77         param = "";
78         return false;
79     }
80     param.reserve(size + 1);
81     param.resize(size);
82     if (napi_get_value_string_utf8(env, args, param.data(), (size + 1), &size) != napi_ok) {
83         HILOGE("can not get string value");
84         param = "";
85         return false;
86     }
87     return true;
88 }
89 
ParseInt32(napi_env env, int32_t &param, napi_value args)90 bool ParseInt32(napi_env env, int32_t &param, napi_value args)
91 {
92     napi_valuetype valuetype;
93     napi_typeof(env, args, &valuetype);
94     if (valuetype != napi_number) {
95         HILOGE("Wrong argument type(%{public}d). Int32 expected.", valuetype);
96         return false;
97     }
98     napi_get_value_int32(env, args, &param);
99     return true;
100 }
101 
ParseBool(napi_env env, bool &param, napi_value args)102 bool ParseBool(napi_env env, bool &param, napi_value args)
103 {
104     napi_valuetype valuetype;
105     napi_typeof(env, args, &valuetype);
106 
107     if (valuetype != napi_boolean) {
108         HILOGE("Wrong argument type(%{public}d). bool expected.", valuetype);
109         return false;
110     }
111     napi_get_value_bool(env, args, &param);
112     return true;
113 }
114 
115 
ParseArrayBuffer(napi_env env, uint8_t** data, size_t &size, napi_value args)116 bool ParseArrayBuffer(napi_env env, uint8_t** data, size_t &size, napi_value args)
117 {
118     napi_status status;
119     napi_valuetype valuetype;
120     napi_typeof(env, args, &valuetype);
121 
122     if (valuetype != napi_object) {
123         HILOGE("Wrong argument type(%{public}d). object expected.", valuetype);
124         return false;
125     }
126 
127     status = napi_get_arraybuffer_info(env, args, reinterpret_cast<void**>(data), &size);
128     if (status != napi_ok) {
129         HILOGE("can not get arraybuffer, error is %{public}d", status);
130         return false;
131     }
132     HILOGI("arraybuffer size is %{public}zu", size);
133     return true;
134 }
135 
ConvertOppTransferInformationToJS(napi_env env, napi_value result, const BluetoothOppTransferInformation& transferInformation)136 napi_status ConvertOppTransferInformationToJS(napi_env env, napi_value result,
137     const BluetoothOppTransferInformation& transferInformation)
138 {
139     HILOGI("ConvertOppTransferInformationToJS called");
140     napi_value id;
141     napi_create_int32(env, transferInformation.GetId(), &id);
142     napi_set_named_property(env, result, "id", id);
143 
144     napi_value fileName;
145     napi_create_string_utf8(env, transferInformation.GetFileName().c_str(), NAPI_AUTO_LENGTH, &fileName);
146     napi_set_named_property(env, result, "fileName", fileName);
147 
148     napi_value filePath;
149     napi_create_string_utf8(env, transferInformation.GetFilePath().c_str(), NAPI_AUTO_LENGTH, &filePath);
150     napi_set_named_property(env, result, "filePath", filePath);
151 
152     napi_value mimeType;
153     napi_create_string_utf8(env, transferInformation.GetMimeType().c_str(), NAPI_AUTO_LENGTH, &mimeType);
154     napi_set_named_property(env, result, "mimeType", mimeType);
155 
156     napi_value deviceName;
157     napi_create_string_utf8(env, transferInformation.GetDeviceName().c_str(), NAPI_AUTO_LENGTH, &deviceName);
158     napi_set_named_property(env, result, "deviceName", deviceName);
159 
160     napi_value deviceAddress;
161     napi_create_string_utf8(env, transferInformation.GetDeviceAddress().c_str(), NAPI_AUTO_LENGTH, &deviceAddress);
162     napi_set_named_property(env, result, "deviceAddress", deviceAddress);
163 
164     napi_value direction;
165     napi_create_int32(env, transferInformation.GetDirection(), &direction);
166     napi_set_named_property(env, result, "direction", direction);
167 
168     napi_value status;
169     napi_create_int32(env, transferInformation.GetStatus(), &status);
170     napi_set_named_property(env, result, "status", status);
171 
172     napi_value failedReason;
173     napi_create_int32(env, transferInformation.GetFailedReason(), &failedReason);
174     napi_set_named_property(env, result, "failedReason", failedReason);
175 
176     napi_value timeStamp;
177     napi_create_int64(env, transferInformation.GetTimeStamp(), &timeStamp);
178     napi_set_named_property(env, result, "timeStamp", timeStamp);
179 
180     napi_value currentBytes;
181     napi_create_int64(env, transferInformation.GetCurrentBytes(), &currentBytes);
182     napi_set_named_property(env, result, "currentBytes", currentBytes);
183 
184     napi_value totalBytes;
185     napi_create_int64(env, transferInformation.GetTotalBytes(), &totalBytes);
186     napi_set_named_property(env, result, "totalBytes", totalBytes);
187 
188     return napi_ok;
189 }
190 
ConvertStringVectorToJS(napi_env env, napi_value result, std::vector<std::string>& stringVector)191 napi_status ConvertStringVectorToJS(napi_env env, napi_value result, std::vector<std::string>& stringVector)
192 {
193     HILOGI("vector size: %{public}zu", stringVector.size());
194     size_t idx = 0;
195 
196     if (stringVector.empty()) {
197         return napi_ok;
198     }
199 
200     for (auto& str : stringVector) {
201         napi_value obj = nullptr;
202         NAPI_BT_CALL_RETURN(napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &obj));
203         NAPI_BT_CALL_RETURN(napi_set_element(env, result, idx, obj));
204         idx++;
205     }
206     return napi_ok;
207 }
208 
ConvertStateChangeParamToJS(napi_env env, napi_value result, const std::string &device, int state, int cause)209 void ConvertStateChangeParamToJS(napi_env env, napi_value result, const std::string &device, int state, int cause)
210 {
211     napi_value deviceId = nullptr;
212     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
213     napi_set_named_property(env, result, "deviceId", deviceId);
214 
215     napi_value profileState = nullptr;
216     napi_create_int32(env, GetProfileConnectionState(state), &profileState);
217     napi_set_named_property(env, result, "state", profileState);
218 
219     napi_value stateChangeCause = nullptr;
220     napi_create_int32(env, cause, &stateChangeCause);
221     napi_set_named_property(env, result, "cause", stateChangeCause);
222 }
223 
ConvertScoStateChangeParamToJS(napi_env env, napi_value result, const std::string &device, int state)224 void ConvertScoStateChangeParamToJS(napi_env env, napi_value result, const std::string &device, int state)
225 {
226     napi_value deviceId = nullptr;
227     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
228     napi_set_named_property(env, result, "deviceId", deviceId);
229 
230     napi_value profileState = nullptr;
231     napi_create_int32(env, GetScoConnectionState(state), &profileState);
232     napi_set_named_property(env, result, "state", profileState);
233 }
234 
ConvertUuidsVectorToJS(napi_env env, napi_value result, const std::vector<std::string> &uuids)235 void ConvertUuidsVectorToJS(napi_env env, napi_value result, const std::vector<std::string> &uuids)
236 {
237     HILOGD("enter");
238     size_t idx = 0;
239 
240     if (uuids.empty()) {
241         return;
242     }
243     HILOGI("size: %{public}zu", uuids.size());
244     for (auto& uuid : uuids) {
245         napi_value uuidValue = nullptr;
246         napi_create_string_utf8(env, uuid.c_str(), NAPI_AUTO_LENGTH, &uuidValue);
247         napi_set_element(env, result, idx, uuidValue);
248         idx++;
249     }
250 }
251 
SetNamedPropertyByInteger(napi_env env, napi_value dstObj, int32_t objName, const char *propName)252 void SetNamedPropertyByInteger(napi_env env, napi_value dstObj, int32_t objName, const char *propName)
253 {
254     napi_value prop = nullptr;
255     if (napi_create_int32(env, objName, &prop) == napi_ok) {
256         napi_set_named_property(env, dstObj, propName, prop);
257     }
258 }
259 
SetNamedPropertyByString(napi_env env, napi_value dstObj, const std::string &strValue, const char *propName)260 void SetNamedPropertyByString(napi_env env, napi_value dstObj, const std::string &strValue, const char *propName)
261 {
262     napi_value prop = nullptr;
263     if (napi_create_string_utf8(env, strValue.c_str(), NAPI_AUTO_LENGTH, &prop) == napi_ok) {
264         napi_set_named_property(env, dstObj, propName, prop);
265     }
266 }
267 
NapiGetNull(napi_env env)268 napi_value NapiGetNull(napi_env env)
269 {
270     napi_value result = nullptr;
271     napi_get_null(env, &result);
272     return result;
273 }
274 
NapiGetBooleanFalse(napi_env env)275 napi_value NapiGetBooleanFalse(napi_env env)
276 {
277     napi_value result = nullptr;
278     napi_get_boolean(env, false, &result);
279     return result;
280 }
281 
NapiGetBooleanTrue(napi_env env)282 napi_value NapiGetBooleanTrue(napi_env env)
283 {
284     napi_value result = nullptr;
285     napi_get_boolean(env, true, &result);
286     return result;
287 }
288 
NapiGetBooleanRet(napi_env env, bool ret)289 napi_value NapiGetBooleanRet(napi_env env, bool ret)
290 {
291     napi_value result = nullptr;
292     napi_get_boolean(env, ret, &result);
293     return result;
294 }
295 
NapiGetUndefinedRet(napi_env env)296 napi_value NapiGetUndefinedRet(napi_env env)
297 {
298     napi_value ret = nullptr;
299     napi_get_undefined(env, &ret);
300     return ret;
301 }
302 
NapiGetInt32Ret(napi_env env, int32_t res)303 napi_value NapiGetInt32Ret(napi_env env, int32_t res)
304 {
305     napi_value ret = nullptr;
306     napi_create_int32(env, res, &ret);
307     return ret;
308 }
309 
GetObserver()310 std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> GetObserver()
311 {
312     return g_Observer;
313 }
314 
GetSysBLEObserver()315 const sysBLEMap &GetSysBLEObserver()
316 {
317     return g_sysBLEObserver;
318 }
319 
GetProfileConnectionState(int state)320 int GetProfileConnectionState(int state)
321 {
322     int32_t profileConnectionState = ProfileConnectionState::STATE_DISCONNECTED;
323     switch (state) {
324         case static_cast<int32_t>(BTConnectState::CONNECTING):
325             HILOGD("STATE_CONNECTING(1)");
326             profileConnectionState = ProfileConnectionState::STATE_CONNECTING;
327             break;
328         case static_cast<int32_t>(BTConnectState::CONNECTED):
329             HILOGD("STATE_CONNECTED(2)");
330             profileConnectionState = ProfileConnectionState::STATE_CONNECTED;
331             break;
332         case static_cast<int32_t>(BTConnectState::DISCONNECTING):
333             HILOGD("STATE_DISCONNECTING(3)");
334             profileConnectionState = ProfileConnectionState::STATE_DISCONNECTING;
335             break;
336         case static_cast<int32_t>(BTConnectState::DISCONNECTED):
337             HILOGD("STATE_DISCONNECTED(0)");
338             profileConnectionState = ProfileConnectionState::STATE_DISCONNECTED;
339             break;
340         default:
341             break;
342     }
343     return profileConnectionState;
344 }
345 
GetProfileId(int profile)346 uint32_t GetProfileId(int profile)
347 {
348     uint32_t profileId = 0;
349     switch (profile) {
350         case static_cast<int32_t>(ProfileId::PROFILE_A2DP_SINK):
351             HILOGD("PROFILE_ID_A2DP_SINK");
352             profileId = PROFILE_ID_A2DP_SINK;
353             break;
354         case static_cast<int32_t>(ProfileId::PROFILE_A2DP_SOURCE):
355             HILOGD("PROFILE_ID_A2DP_SRC");
356             profileId = PROFILE_ID_A2DP_SRC;
357             break;
358         case static_cast<int32_t>(ProfileId::PROFILE_AVRCP_CT):
359             HILOGD("PROFILE_ID_AVRCP_CT");
360             profileId = PROFILE_ID_AVRCP_CT;
361             break;
362         case static_cast<int32_t>(ProfileId::PROFILE_AVRCP_TG):
363             HILOGD("PROFILE_ID_AVRCP_TG");
364             profileId = PROFILE_ID_AVRCP_TG;
365             break;
366         case static_cast<int32_t>(ProfileId::PROFILE_HANDS_FREE_AUDIO_GATEWAY):
367             HILOGD("PROFILE_ID_HFP_AG");
368             profileId = PROFILE_ID_HFP_AG;
369             break;
370         case static_cast<int32_t>(ProfileId::PROFILE_HANDS_FREE_UNIT):
371             HILOGD("PROFILE_ID_HFP_HF");
372             profileId = PROFILE_ID_HFP_HF;
373             break;
374         case static_cast<int32_t>(ProfileId::PROFILE_PBAP_CLIENT):
375             HILOGD("PROFILE_ID_PBAP_PCE");
376             profileId = PROFILE_ID_PBAP_PCE;
377             break;
378         case static_cast<int32_t>(ProfileId::PROFILE_PBAP_SERVER):
379             HILOGD("PROFILE_ID_PBAP_PSE");
380             profileId = PROFILE_ID_PBAP_PSE;
381             break;
382         case static_cast<int32_t>(ProfileId::PROFILE_HID_HOST):
383             HILOGD("PROFILE_HID_HOST");
384             profileId = PROFILE_ID_HID_HOST;
385             break;
386         default:
387             break;
388     }
389     return profileId;
390 }
391 
GetScoConnectionState(int state)392 int GetScoConnectionState(int state)
393 {
394     int32_t scoState = ScoState::SCO_DISCONNECTED;
395     switch (state) {
396         case static_cast<int32_t>(HfpScoConnectState::SCO_CONNECTING):
397             HILOGD("SCO_CONNECTING(1)");
398             scoState = ScoState::SCO_CONNECTING;
399             break;
400         case static_cast<int32_t>(HfpScoConnectState::SCO_CONNECTED):
401             HILOGD("SCO_CONNECTED(3)");
402             scoState = ScoState::SCO_CONNECTED;
403             break;
404         case static_cast<int32_t>(HfpScoConnectState::SCO_DISCONNECTING):
405             HILOGD("SCO_DISCONNECTING(2)");
406             scoState = ScoState::SCO_DISCONNECTING;
407             break;
408         case static_cast<int32_t>(HfpScoConnectState::SCO_DISCONNECTED):
409             HILOGD("SCO_DISCONNECTED(0)");
410             scoState = ScoState::SCO_DISCONNECTED;
411             break;
412         default:
413             break;
414     }
415     return scoState;
416 }
417 
RegisterSysBLEObserver( const std::shared_ptr<BluetoothCallbackInfo> &info, int32_t callbackIndex, const std::string &type)418 void RegisterSysBLEObserver(
419     const std::shared_ptr<BluetoothCallbackInfo> &info, int32_t callbackIndex, const std::string &type)
420 {
421     if (callbackIndex >= static_cast<int32_t>(ARGS_SIZE_THREE)) {
422         return;
423     }
424     std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
425     HILOGI("type: %{public}s, index: %{public}d", type.c_str(), callbackIndex);
426     g_sysBLEObserver[type][callbackIndex] = info;
427 }
428 
UnregisterSysBLEObserver(const std::string &type)429 void UnregisterSysBLEObserver(const std::string &type)
430 {
431     std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
432     auto itor = g_sysBLEObserver.find(type);
433     if (itor != g_sysBLEObserver.end()) {
434         g_sysBLEObserver.erase(itor);
435     }
436 }
437 
DoInJsMainThread(napi_env env, std::function<void(void)> func)438 int DoInJsMainThread(napi_env env, std::function<void(void)> func)
439 {
440     if (napi_send_event(env, func, napi_eprio_high) != napi_ok) {
441         HILOGE("Failed to SendEvent");
442         return -1;
443     }
444     return 0;
445 }
446 
IsValidAddress(std::string bdaddr)447 bool IsValidAddress(std::string bdaddr)
448 {
449 #if defined(IOS_PLATFORM)
450     const std::regex deviceIdRegex("^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$");
451     return regex_match(bdaddr, deviceIdRegex);
452 #else
453     const std::regex deviceIdRegex("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$");
454     return regex_match(bdaddr, deviceIdRegex);
455 #endif
456 }
457 
IsValidTransport(int transport)458 bool IsValidTransport(int transport)
459 {
460     return transport == BT_TRANSPORT_BREDR || transport == BT_TRANSPORT_BLE;
461 }
462 
IsValidConnectStrategy(int strategy)463 bool IsValidConnectStrategy(int strategy)
464 {
465     return strategy == static_cast<int>(BTStrategyType::CONNECTION_ALLOWED)
466         || strategy == static_cast<int>(BTStrategyType::CONNECTION_FORBIDDEN);
467 }
468 
NapiIsBoolean(napi_env env, napi_value value)469 napi_status NapiIsBoolean(napi_env env, napi_value value)
470 {
471     napi_valuetype valuetype = napi_undefined;
472     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
473     NAPI_BT_RETURN_IF(valuetype != napi_boolean, "Wrong argument type. Boolean expected.", napi_boolean_expected);
474     return napi_ok;
475 }
476 
NapiIsNumber(napi_env env, napi_value value)477 napi_status NapiIsNumber(napi_env env, napi_value value)
478 {
479     napi_valuetype valuetype = napi_undefined;
480     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
481     NAPI_BT_RETURN_IF(valuetype != napi_number, "Wrong argument type. Number expected.", napi_number_expected);
482     return napi_ok;
483 }
484 
NapiIsString(napi_env env, napi_value value)485 napi_status NapiIsString(napi_env env, napi_value value)
486 {
487     napi_valuetype valuetype = napi_undefined;
488     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
489     NAPI_BT_RETURN_IF(valuetype != napi_string, "Wrong argument type. String expected.", napi_string_expected);
490     return napi_ok;
491 }
492 
NapiIsFunction(napi_env env, napi_value value)493 napi_status NapiIsFunction(napi_env env, napi_value value)
494 {
495     napi_valuetype valuetype = napi_undefined;
496     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
497     if (valuetype != napi_function) {
498         HILOGD("Wrong argument type. Function expected.");
499         return napi_function_expected;
500     }
501     NAPI_BT_RETURN_IF(valuetype != napi_function, "Wrong argument type. Function expected.", napi_function_expected);
502     return napi_ok;
503 }
504 
NapiIsArrayBuffer(napi_env env, napi_value value)505 napi_status NapiIsArrayBuffer(napi_env env, napi_value value)
506 {
507     bool isArrayBuffer = false;
508     NAPI_BT_CALL_RETURN(napi_is_arraybuffer(env, value, &isArrayBuffer));
509     NAPI_BT_RETURN_IF(!isArrayBuffer, "Expected arraybuffer type", napi_arraybuffer_expected);
510     return napi_ok;
511 }
512 
NapiIsArray(napi_env env, napi_value value)513 napi_status NapiIsArray(napi_env env, napi_value value)
514 {
515     bool isArray = false;
516     NAPI_BT_CALL_RETURN(napi_is_array(env, value, &isArray));
517     NAPI_BT_RETURN_IF(!isArray, "Expected array type", napi_array_expected);
518     return napi_ok;
519 }
520 
NapiIsObject(napi_env env, napi_value value)521 napi_status NapiIsObject(napi_env env, napi_value value)
522 {
523     napi_valuetype valuetype = napi_undefined;
524     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
525     NAPI_BT_RETURN_IF(valuetype != napi_object, "Wrong argument type. Object expected.", napi_object_expected);
526     return napi_ok;
527 }
528 
ParseNumberParams(napi_env env, napi_value object, const char *name, bool &outExist, napi_value &outParam)529 napi_status ParseNumberParams(napi_env env, napi_value object, const char *name, bool &outExist,
530     napi_value &outParam)
531 {
532     bool hasProperty = false;
533     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &hasProperty));
534     if (hasProperty) {
535         napi_value property;
536         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
537         napi_valuetype valuetype;
538         NAPI_BT_CALL_RETURN(napi_typeof(env, property, &valuetype));
539         NAPI_BT_RETURN_IF(valuetype != napi_number, "Wrong argument type, number expected", napi_number_expected);
540         outParam = property;
541     }
542     outExist = hasProperty;
543     return napi_ok;
544 }
545 
ParseInt32Params(napi_env env, napi_value object, const char *name, bool &outExist, int32_t &outParam)546 napi_status ParseInt32Params(napi_env env, napi_value object, const char *name, bool &outExist,
547     int32_t &outParam)
548 {
549     bool exist = false;
550     napi_value param;
551     NAPI_BT_CALL_RETURN(ParseNumberParams(env, object, name, exist, param));
552     if (exist) {
553         int32_t num = 0;
554         NAPI_BT_CALL_RETURN(napi_get_value_int32(env, param, &num));
555         outParam = num;
556     }
557     outExist = exist;
558     return napi_ok;
559 }
560 
ParseUint32Params(napi_env env, napi_value object, const char *name, bool &outExist, uint32_t &outParam)561 napi_status ParseUint32Params(napi_env env, napi_value object, const char *name, bool &outExist,
562     uint32_t &outParam)
563 {
564     bool exist = false;
565     napi_value param;
566     NAPI_BT_CALL_RETURN(ParseNumberParams(env, object, name, exist, param));
567     if (exist) {
568         uint32_t num = 0;
569         NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, param, &num));
570         outParam = num;
571     }
572     outExist = exist;
573     return napi_ok;
574 }
575 
ParseBooleanParams(napi_env env, napi_value object, const char *name, bool &outExist, bool &outParam)576 napi_status ParseBooleanParams(napi_env env, napi_value object, const char *name, bool &outExist, bool &outParam)
577 {
578     bool hasProperty = false;
579     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &hasProperty));
580     if (hasProperty) {
581         napi_value property;
582         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
583         napi_valuetype valuetype;
584         NAPI_BT_CALL_RETURN(napi_typeof(env, property, &valuetype));
585         NAPI_BT_RETURN_IF(valuetype != napi_boolean, "Wrong argument type, boolean expected", napi_boolean_expected);
586 
587         bool param = false;
588         NAPI_BT_CALL_RETURN(napi_get_value_bool(env, property, &param));
589         outParam = param;
590     }
591     outExist = hasProperty;
592     return napi_ok;
593 }
594 
595 // Only used for optional paramters
ParseStringParams(napi_env env, napi_value object, const char *name, bool &outExist, std::string &outParam)596 napi_status ParseStringParams(napi_env env, napi_value object, const char *name, bool &outExist,
597     std::string &outParam)
598 {
599     bool hasProperty = false;
600     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &hasProperty));
601     if (hasProperty) {
602         napi_value property;
603         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
604         napi_valuetype valuetype;
605         NAPI_BT_CALL_RETURN(napi_typeof(env, property, &valuetype));
606         NAPI_BT_RETURN_IF(valuetype != napi_string, "Wrong argument type, string expected", napi_string_expected);
607 
608         std::string param {};
609         bool isSuccess = ParseString(env, param, property);
610         if (!isSuccess) {
611             return napi_invalid_arg;
612         }
613         outParam = std::move(param);
614     }
615     outExist = hasProperty;
616     return napi_ok;
617 }
618 
ParseArrayBufferParams(napi_env env, napi_value object, const char *name, bool &outExist, std::vector<uint8_t> &outParam)619 napi_status ParseArrayBufferParams(napi_env env, napi_value object, const char *name, bool &outExist,
620     std::vector<uint8_t> &outParam)
621 {
622     bool hasProperty = false;
623     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &hasProperty));
624     if (hasProperty) {
625         napi_value property;
626         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
627         bool isArrayBuffer = false;
628         NAPI_BT_CALL_RETURN(napi_is_arraybuffer(env, property, &isArrayBuffer));
629         NAPI_BT_RETURN_IF(!isArrayBuffer, "Wrong argument type, arraybuffer expected", napi_arraybuffer_expected);
630 
631         uint8_t *data = nullptr;
632         size_t size = 0;
633         bool isSuccess = ParseArrayBuffer(env, &data, size, property);
634         if (!isSuccess) {
635             HILOGE("ParseArrayBuffer faild.");
636             return napi_invalid_arg;
637         }
638         outParam = std::vector<uint8_t>(data, data + size);
639     }
640     outExist = hasProperty;
641     return napi_ok;
642 }
643 
ParseUuidParams(napi_env env, napi_value object, const char *name, bool &outExist, UUID &outUuid)644 napi_status ParseUuidParams(napi_env env, napi_value object, const char *name, bool &outExist, UUID &outUuid)
645 {
646     bool exist = false;
647     std::string uuid {};
648     NAPI_BT_CALL_RETURN(ParseStringParams(env, object, name, exist, uuid));
649     if (exist) {
650         if (!IsValidUuid(uuid)) {
651             HILOGE("match the UUID faild.");
652             return napi_invalid_arg;
653         }
654         outUuid = ParcelUuid::FromString(uuid);
655     }
656     outExist = exist;
657     return napi_ok;
658 }
659 
660 // This function applies to interfaces with a single address as a parameter.
CheckDeivceIdParam(napi_env env, napi_callback_info info, std::string &addr)661 bool CheckDeivceIdParam(napi_env env, napi_callback_info info, std::string &addr)
662 {
663     size_t argc = ARGS_SIZE_ONE;
664     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
665     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok, "call failed.", false);
666     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Wrong argument type", false);
667     NAPI_BT_RETURN_IF(!ParseString(env, addr, argv[PARAM0]), "ParseString failed", false);
668     NAPI_BT_RETURN_IF(!IsValidAddress(addr), "Invalid addr", false);
669     return true;
670 }
671 
CheckProfileIdParam(napi_env env, napi_callback_info info, int &profileId)672 bool CheckProfileIdParam(napi_env env, napi_callback_info info, int &profileId)
673 {
674     size_t argc = ARGS_SIZE_ONE;
675     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
676     napi_value thisVar = nullptr;
677     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr) != napi_ok, "call failed.", false);
678     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Wrong argument type", false);
679     NAPI_BT_RETURN_IF(!ParseInt32(env, profileId, argv[PARAM0]), "ParseInt32 failed", false);
680     return true;
681 }
682 
CheckProfileIdParamEx(napi_env env, napi_callback_info info, int &profileId, size_t &argc)683 bool CheckProfileIdParamEx(napi_env env, napi_callback_info info, int &profileId, size_t &argc)
684 {
685     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
686     napi_value thisVar = nullptr;
687     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr) != napi_ok, "call failed.", false);
688     NAPI_BT_RETURN_IF(argc > ARGS_SIZE_ONE, "Wrong argument type", false);
689     if (argc == ARGS_SIZE_ONE) {
690         NAPI_BT_RETURN_IF(!ParseInt32(env, profileId, argv[PARAM0]), "ParseInt32 failed", false);
691     }
692     return true;
693 }
694 
CheckSetDevicePairingConfirmationParam(napi_env env, napi_callback_info info, std::string &addr, bool &accept)695 bool CheckSetDevicePairingConfirmationParam(napi_env env, napi_callback_info info, std::string &addr, bool &accept)
696 {
697     size_t argc = ARGS_SIZE_TWO;
698     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
699     napi_value thisVar = nullptr;
700     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr) != napi_ok, "call failed.", false);
701     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Wrong argument type", false);
702     NAPI_BT_RETURN_IF(!ParseString(env, addr, argv[PARAM0]), "ParseString failed", false);
703     NAPI_BT_RETURN_IF(!IsValidAddress(addr), "Invalid addr", false);
704     NAPI_BT_RETURN_IF(!ParseBool(env, accept, argv[PARAM1]), "ParseBool failed", false);
705     return true;
706 }
707 
CheckLocalNameParam(napi_env env, napi_callback_info info, std::string &name)708 bool CheckLocalNameParam(napi_env env, napi_callback_info info, std::string &name)
709 {
710     size_t argc = ARGS_SIZE_ONE;
711     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
712     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok, "call failed.", false);
713     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Wrong argument type", false);
714     NAPI_BT_RETURN_IF(!ParseString(env, name, argv[PARAM0]), "ParseString failed", false);
715     return true;
716 }
717 
CheckSetBluetoothScanModeParam(napi_env env, napi_callback_info info, int32_t &mode, int32_t &duration)718 bool CheckSetBluetoothScanModeParam(napi_env env, napi_callback_info info, int32_t &mode, int32_t &duration)
719 {
720     size_t argc = ARGS_SIZE_TWO;
721     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
722     napi_value thisVar = nullptr;
723     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr) != napi_ok, "call failed.", false);
724     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Wrong argument type", false);
725     NAPI_BT_RETURN_IF(!ParseInt32(env, mode, argv[PARAM0]), "ParseInt32 failed", false);
726     NAPI_BT_RETURN_IF(!ParseInt32(env, duration, argv[PARAM1]), "ParseInt32 failed", false);
727     return true;
728 }
729 
CheckEmptyParam(napi_env env, napi_callback_info info)730 napi_status CheckEmptyParam(napi_env env, napi_callback_info info)
731 {
732     size_t argc = ARGS_SIZE_ZERO;
733     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr));
734     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ZERO, "Requires 0 argument.", napi_invalid_arg);
735     return napi_ok;
736 }
737 
NapiCheckObjectPropertiesName(napi_env env, napi_value object, const std::vector<std::string> &names)738 napi_status NapiCheckObjectPropertiesName(napi_env env, napi_value object, const std::vector<std::string> &names)
739 {
740     uint32_t len = 0;
741     napi_value properties;
742     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
743     NAPI_BT_CALL_RETURN(napi_get_property_names(env, object, &properties));
744     NAPI_BT_CALL_RETURN(napi_get_array_length(env, properties, &len));
745     for (uint32_t i = 0; i < len; ++i) {
746         std::string name {};
747         napi_value actualName;
748         NAPI_BT_CALL_RETURN(napi_get_element(env, properties, i, &actualName));
749         NAPI_BT_CALL_RETURN(NapiParseString(env, actualName, name));
750         if (std::find(names.begin(), names.end(), name) == names.end()) {
751             HILOGE("Unexpect object property name: \"%{public}s\"", name.c_str());
752             return napi_invalid_arg;
753         }
754     }
755     return napi_ok;
756 }
757 
CheckSetConnectStrategyParam(napi_env env, napi_callback_info info, std::string &addr, int32_t &strategy)758 napi_status CheckSetConnectStrategyParam(napi_env env, napi_callback_info info, std::string &addr, int32_t &strategy)
759 {
760     size_t argc = ARGS_SIZE_THREE;
761     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
762     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
763     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE, "Requires 2 or 3 arguments.", napi_invalid_arg);
764     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
765     NAPI_BT_RETURN_IF(!ParseInt32(env, strategy, argv[PARAM1]), "ParseInt failed", napi_invalid_arg);
766     NAPI_BT_RETURN_IF(!IsValidConnectStrategy(strategy), "Invalid strategy", napi_invalid_arg);
767     return napi_ok;
768 }
769 
CheckDeviceAddressParam(napi_env env, napi_callback_info info, std::string &addr)770 napi_status CheckDeviceAddressParam(napi_env env, napi_callback_info info, std::string &addr)
771 {
772     size_t argc = ARGS_SIZE_TWO;
773     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
774     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
775     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO, "Requires 1 or 2 arguments.", napi_invalid_arg);
776     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
777     return napi_ok;
778 }
779 
IsAccessAuthorizationValid(int32_t accessAuthorization)780 bool IsAccessAuthorizationValid(int32_t accessAuthorization)
781 {
782     return accessAuthorization == static_cast<int32_t>(AccessAuthorization::UNKNOWN) ||
783         accessAuthorization == static_cast<int32_t>(AccessAuthorization::ALLOWED) ||
784         accessAuthorization == static_cast<int32_t>(AccessAuthorization::REJECTED);
785 }
786 
CheckAccessAuthorizationParam(napi_env env, napi_callback_info info, std::string &addr, int32_t &accessAuthorization)787 napi_status CheckAccessAuthorizationParam(napi_env env, napi_callback_info info, std::string &addr,
788     int32_t &accessAuthorization)
789 {
790     size_t argc = ARGS_SIZE_THREE;
791     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
792     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
793     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE, "Requires 2 or 3 arguments.", napi_invalid_arg);
794     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
795     NAPI_BT_RETURN_IF(!ParseInt32(env, accessAuthorization, argv[PARAM1]), "ParseInt failed", napi_invalid_arg);
796     NAPI_BT_RETURN_IF(!IsAccessAuthorizationValid(accessAuthorization),
797         "Invalid accessAuthorization", napi_invalid_arg);
798     return napi_ok;
799 }
800 
NapiGetOnOffCallbackName(napi_env env, napi_callback_info info, std::string &name)801 napi_status NapiGetOnOffCallbackName(napi_env env, napi_callback_info info, std::string &name)
802 {
803     size_t argc = ARGS_SIZE_TWO;
804     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
805     napi_value thisVar = nullptr;
806     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
807     NAPI_BT_RETURN_IF(argc == ARGS_SIZE_ZERO, "Requires at least 1 arguments", napi_invalid_arg);
808 
809     std::string type {};
810     NAPI_BT_CALL_RETURN(NapiParseString(env, argv[PARAM0], type));
811 
812     name = type;
813     return napi_ok;
814 }
815 }  // namespace Bluetooth
816 }  // namespace OHOS
817