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 ¶m, napi_value args)64 bool ParseString(napi_env env, string ¶m, 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 ¶m, napi_value args)90 bool ParseInt32(napi_env env, int32_t ¶m, 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, ¶m);
99 return true;
100 }
101
ParseBool(napi_env env, bool ¶m, napi_value args)102 bool ParseBool(napi_env env, bool ¶m, 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, ¶m);
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(), ¤tBytes);
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, ¶m));
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