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