• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param, 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 &param, 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, &param);
104     return true;
105 }
106 
ParseBool(napi_env env,bool & param,napi_value args)107 bool ParseBool(napi_env env, bool &param, 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, &param);
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(), &currentBytes);
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(), &currentCount);
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, &param));
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