• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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_parser_utils"
17 #endif
18 
19 #include "napi_parser_utils.h"
20 
21 #include <string>
22 #include <vector>
23 
24 #include "napi_async_callback.h"
25 #include <cinttypes>
26 namespace OHOS {
27 namespace Bluetooth {
28 
29 // shall check object type is napi_object before, if it's other type, return false
30 // If the 'name' field is not exist, or napi function call error, return false
NapiIsObjectPropertyExist(napi_env env,napi_value object,const char * name)31 bool NapiIsObjectPropertyExist(napi_env env, napi_value object, const char *name)
32 {
33     auto status = NapiIsObject(env, object);
34     if (status != napi_ok) {
35         HILOGE("expect object");
36         return false;
37     }
38     bool exist = false;
39     status = napi_has_named_property(env, object, name, &exist);
40     if (status != napi_ok) {
41         HILOGE("Get object property failed, name: %{public}s", name);
42         return false;
43     }
44     return exist;
45 }
46 
NapiParseGattService(napi_env env,napi_value object,NapiGattService & outService)47 napi_status NapiParseGattService(napi_env env, napi_value object, NapiGattService &outService)
48 {
49     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "isPrimary", "characteristics",
50         "includeServices"}));
51 
52     std::string uuid {};
53     bool isPrimary = true;
54     std::vector<NapiBleCharacteristic> characteristics {};
55     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
56     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
57     NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "isPrimary", isPrimary));
58     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "characteristics", characteristics));
59     if (NapiIsObjectPropertyExist(env, object, "includeServices")) {
60         std::vector<NapiGattService> includeServices {};
61         NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "includeServices", includeServices));
62         outService.includeServices = std::move(includeServices);
63     }
64     outService.serviceUuid = UUID::FromString(uuid);
65     outService.isPrimary = isPrimary;
66     outService.characteristics = std::move(characteristics);
67     return napi_ok;
68 }
69 
70 namespace {
71 const NapiGattPermission DEFAULT_GATT_PERMISSIONS = {
72     .readable = true,
73     .writeable = true,
74 };
75 const NapiGattProperties DEFAULT_GATT_PROPERTIES = {
76     .write = true,
77     .writeNoResponse = true,
78     .read = true,
79 };
ConvertGattPermissions(const NapiGattPermission & napiPermissions)80 uint16_t ConvertGattPermissions(const NapiGattPermission &napiPermissions)
81 {
82     uint16_t permissions = 0;
83     if (napiPermissions.readable) {
84         permissions |= static_cast<uint16_t>(GattPermission::READABLE);
85     }
86     if (napiPermissions.readEncrypted) {
87         permissions |= static_cast<uint16_t>(GattPermission::READ_ENCRYPTED);
88     }
89     if (napiPermissions.readEncryptedMitm) {
90         permissions |= static_cast<uint16_t>(GattPermission::READ_ENCRYPTED_MITM);
91     }
92     if (napiPermissions.writeable) {
93         permissions |= static_cast<uint16_t>(GattPermission::WRITEABLE);
94     }
95     if (napiPermissions.writeEncrypted) {
96         permissions |= static_cast<uint16_t>(GattPermission::WRITE_ENCRYPTED);
97     }
98     if (napiPermissions.writeEncryptedMitm) {
99         permissions |= static_cast<uint16_t>(GattPermission::WRITE_ENCRYPTED_MITM);
100     }
101     if (napiPermissions.writeSigned) {
102         permissions |= static_cast<uint16_t>(GattPermission::WRITE_SIGNED);
103     }
104     if (napiPermissions.writeSignedMitm) {
105         permissions |= static_cast<uint16_t>(GattPermission::WRITE_SIGNED_MITM);
106     }
107     return permissions;
108 }
ConvertGattProperties(const NapiGattProperties & napiProperties)109 uint16_t ConvertGattProperties(const NapiGattProperties &napiProperties)
110 {
111     uint16_t properties = 0;
112     if (napiProperties.read) {
113         properties |= static_cast<uint16_t>(GattCharacteristic::READ);
114     }
115     if (napiProperties.write) {
116         properties |= static_cast<uint16_t>(GattCharacteristic::WRITE);
117     }
118     if (napiProperties.writeNoResponse) {
119         properties |= static_cast<uint16_t>(GattCharacteristic::WRITE_WITHOUT_RESPONSE);
120     }
121     if (napiProperties.notify) {
122         properties |= static_cast<uint16_t>(GattCharacteristic::NOTIFY);
123     }
124     if (napiProperties.indicate) {
125         properties |= static_cast<uint16_t>(GattCharacteristic::INDICATE);
126     }
127     if (napiProperties.broadcast) {
128         properties |= static_cast<uint16_t>(GattCharacteristic::BROADCAST);
129     }
130     if (napiProperties.authenticatedSignedWrite) {
131         properties |= static_cast<uint16_t>(GattCharacteristic::AUTHENTICATED_SIGNED_WRITES);
132     }
133     if (napiProperties.extendedProperties) {
134         properties |= static_cast<uint16_t>(GattCharacteristic::EXTENDED_PROPERTIES);
135     }
136     return properties;
137 }
138 }  // namespace {}
139 
NapiParseGattCharacteristic(napi_env env,napi_value object,NapiBleCharacteristic & outCharacteristic)140 napi_status NapiParseGattCharacteristic(napi_env env, napi_value object, NapiBleCharacteristic &outCharacteristic)
141 {
142     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
143         "characteristicValue", "descriptors", "properties", "characteristicValueHandle", "permissions"}));
144 
145     std::string serviceUuid {};
146     std::string characterUuid {};
147     std::vector<uint8_t> characterValue {};
148     std::vector<NapiBleDescriptor> descriptors {};
149     uint32_t characteristicValueHandle = 0;
150     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
151     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
152     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
153     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
154     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "descriptors", descriptors));
155 
156     NapiGattProperties properties = DEFAULT_GATT_PROPERTIES;
157     if (NapiIsObjectPropertyExist(env, object, "properties"))  {
158         NAPI_BT_CALL_RETURN(NapiParseObjectGattProperties(env, object, "properties", properties));
159     }
160     if (NapiIsObjectPropertyExist(env, object, "characteristicValueHandle")) {
161         NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "characteristicValueHandle", characteristicValueHandle));
162         NAPI_BT_RETURN_IF(characteristicValueHandle > 0xFFFF, "Invalid characteristicValueHandle", napi_invalid_arg);
163     }
164     NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
165     if (NapiIsObjectPropertyExist(env, object, "permissions")) {
166         NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
167     }
168 
169     outCharacteristic.serviceUuid = UUID::FromString(serviceUuid);
170     outCharacteristic.characteristicUuid = UUID::FromString(characterUuid);
171     outCharacteristic.characteristicValue = std::move(characterValue);
172     outCharacteristic.descriptors = std::move(descriptors);
173     outCharacteristic.properties = ConvertGattProperties(properties);
174     outCharacteristic.characteristicValueHandle = static_cast<uint16_t>(characteristicValueHandle);
175     outCharacteristic.permissions = ConvertGattPermissions(permissions);
176     return napi_ok;
177 }
178 
NapiParseGattDescriptor(napi_env env,napi_value object,NapiBleDescriptor & outDescriptor)179 napi_status NapiParseGattDescriptor(napi_env env, napi_value object, NapiBleDescriptor &outDescriptor)
180 {
181     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
182         "descriptorUuid", "descriptorValue", "descriptorHandle", "permissions"}));
183 
184     std::string serviceUuid {};
185     std::string characterUuid {};
186     std::string descriptorUuid {};
187     std::vector<uint8_t> descriptorValue {};
188     uint32_t descriptorHandle = 0;
189     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
190     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
191     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
192     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "descriptorUuid", descriptorUuid));
193     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "descriptorValue", descriptorValue));
194 
195     if (NapiIsObjectPropertyExist(env, object, "descriptorHandle")) {
196         NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "descriptorHandle", descriptorHandle));
197         NAPI_BT_RETURN_IF(descriptorHandle > 0xFFFF, "Invalid descriptorHandle", napi_invalid_arg);
198     }
199     NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
200     if (NapiIsObjectPropertyExist(env, object, "permissions")) {
201         NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
202     }
203 
204     outDescriptor.serviceUuid = UUID::FromString(serviceUuid);
205     outDescriptor.characteristicUuid = UUID::FromString(characterUuid);
206     outDescriptor.descriptorUuid = UUID::FromString(descriptorUuid);
207     outDescriptor.descriptorValue = std::move(descriptorValue);
208     outDescriptor.descriptorHandle = static_cast<uint16_t>(descriptorHandle);
209     outDescriptor.permissions = ConvertGattPermissions(permissions);
210     return napi_ok;
211 }
212 
NapiParseNotifyCharacteristic(napi_env env,napi_value object,NapiNotifyCharacteristic & outCharacter)213 napi_status NapiParseNotifyCharacteristic(napi_env env, napi_value object, NapiNotifyCharacteristic &outCharacter)
214 {
215     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
216         "characteristicValue", "confirm"}));
217 
218     std::string serviceUuid {};
219     std::string characterUuid {};
220     std::vector<uint8_t> characterValue {};
221     bool confirm = false;
222     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
223     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
224     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
225     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
226     NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "confirm", confirm));
227 
228     outCharacter.serviceUuid = UUID::FromString(serviceUuid);
229     outCharacter.characterUuid = UUID::FromString(characterUuid);
230     outCharacter.characterValue = std::move(characterValue);
231     outCharacter.confirm = confirm;
232     return napi_ok;
233 }
234 
NapiParseGattsServerResponse(napi_env env,napi_value object,NapiGattsServerResponse & rsp)235 napi_status NapiParseGattsServerResponse(napi_env env, napi_value object, NapiGattsServerResponse &rsp)
236 {
237     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"deviceId", "transId", "status", "offset",
238         "value"}));
239 
240     std::string deviceId {};
241     int transId = 0;
242     int status = 0;
243     int offset = 0;
244     std::vector<uint8_t> value {};
245     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
246     NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "deviceId", deviceId));
247     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "transId", transId));
248     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "status", status));
249     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "offset", offset));
250     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "value", value));
251 
252     rsp.deviceId = deviceId;
253     rsp.transId = transId;
254     rsp.status = status;
255     rsp.offset = offset;
256     rsp.value = std::move(value);
257     return napi_ok;
258 }
259 
NapiParseObjectGattPermissions(napi_env env,napi_value object,const char * name,NapiGattPermission & outPermissions)260 napi_status NapiParseObjectGattPermissions(napi_env env, napi_value object, const char *name,
261     NapiGattPermission &outPermissions)
262 {
263     napi_value permissionObject;
264     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
265     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, permissionObject));
266     // Parse permission object
267     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, permissionObject, {"read", "readEncrypted",
268         "readEncryptedMitm", "write", "writeEncrypted", "writeEncryptedMitm", "writeSigned", "writeSignedMitm"}));
269 
270     bool isExist;
271     NapiGattPermission permissions {};
272     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
273         env, permissionObject, "read", permissions.readable, isExist));
274     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
275         env, permissionObject, "readEncrypted", permissions.readEncrypted, isExist));
276     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
277         env, permissionObject, "readEncryptedMitm", permissions.readEncryptedMitm, isExist));
278     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
279         env, permissionObject, "write", permissions.writeable, isExist));
280     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
281         env, permissionObject, "writeEncrypted", permissions.writeEncrypted, isExist));
282     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
283         env, permissionObject, "writeEncryptedMitm", permissions.writeEncryptedMitm, isExist));
284     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
285         env, permissionObject, "writeSigned", permissions.writeSigned, isExist));
286     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
287         env, permissionObject, "writeSignedMitm", permissions.writeSignedMitm, isExist));
288     outPermissions = permissions;
289     return napi_ok;
290 }
291 
NapiParseObjectGattProperties(napi_env env,napi_value object,const char * name,NapiGattProperties & outProperties)292 napi_status NapiParseObjectGattProperties(napi_env env, napi_value object, const char *name,
293     NapiGattProperties &outProperties)
294 {
295     napi_value propertiesObject;
296     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
297     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, propertiesObject));
298     // Parse properties object
299     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, propertiesObject, {"write", "writeNoResponse",
300         "read", "notify", "indicate", "broadcast", "authenticatedSignedWrite", "extendedProperties"}));
301 
302     bool isExist;
303     NapiGattProperties properties {};
304     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
305         env, propertiesObject, "write", properties.write, isExist));
306     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
307         env, propertiesObject, "writeNoResponse", properties.writeNoResponse, isExist));
308     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
309         env, propertiesObject, "read", properties.read, isExist));
310     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
311         env, propertiesObject, "notify", properties.notify, isExist));
312     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
313         env, propertiesObject, "indicate", properties.indicate, isExist));
314     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
315         env, propertiesObject, "broadcast", properties.broadcast, isExist));
316     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
317         env, propertiesObject, "authenticatedSignedWrite", properties.authenticatedSignedWrite, isExist));
318     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
319         env, propertiesObject, "extendedProperties", properties.extendedProperties, isExist));
320     outProperties = properties;
321     return napi_ok;
322 }
323 
NapiParseBoolean(napi_env env,napi_value value,bool & outBoolean)324 napi_status NapiParseBoolean(napi_env env, napi_value value, bool &outBoolean)
325 {
326     bool boolean = false;
327     NAPI_BT_CALL_RETURN(NapiIsBoolean(env, value));
328     NAPI_BT_CALL_RETURN(napi_get_value_bool(env, value, &boolean));
329     outBoolean = boolean;
330     return napi_ok;
331 }
332 
NapiParseInt32(napi_env env,napi_value value,int32_t & outNum)333 napi_status NapiParseInt32(napi_env env, napi_value value, int32_t &outNum)
334 {
335     int32_t num = 0;
336     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
337     NAPI_BT_CALL_RETURN(napi_get_value_int32(env, value, &num));
338     outNum = num;
339     return napi_ok;
340 }
341 
NapiParseUint32(napi_env env,napi_value value,uint32_t & outNum)342 napi_status NapiParseUint32(napi_env env, napi_value value, uint32_t &outNum)
343 {
344     uint32_t num = 0;
345     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
346     NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, value, &num));
347     outNum = num;
348     return napi_ok;
349 }
350 
NapiParseString(napi_env env,napi_value value,std::string & outStr)351 napi_status NapiParseString(napi_env env, napi_value value, std::string &outStr)
352 {
353     std::string str {};
354     NAPI_BT_CALL_RETURN(NapiIsString(env, value));
355     NAPI_BT_RETURN_IF(!ParseString(env, str, value), "parse string failed", napi_invalid_arg);
356     outStr = std::move(str);
357     return napi_ok;
358 }
359 
NapiParseStringArray(napi_env env,napi_value value,std::vector<std::string> & outStrVec)360 napi_status NapiParseStringArray(napi_env env, napi_value value, std::vector<std::string> &outStrVec)
361 {
362     NAPI_BT_CALL_RETURN(NapiIsArray(env, value));
363     uint32_t length = 0;
364     std::string param {};
365     std::vector<std::string> strVec {};
366     napi_get_array_length(env, value, &length);
367     for (size_t i = 0; i < length; i++) {
368         napi_value result;
369         napi_get_element(env, value, i, &result);
370         NAPI_BT_CALL_RETURN(NapiParseString(env, result, param));
371         strVec.push_back(param);
372     }
373     outStrVec = std::move(strVec);
374     return napi_ok;
375 }
376 
NapiParseFileHolderArray(napi_env env,napi_value value,std::vector<FileHolder> & outFileHolderVec)377 napi_status NapiParseFileHolderArray(napi_env env, napi_value value, std::vector<FileHolder> &outFileHolderVec)
378 {
379     NAPI_BT_CALL_RETURN(NapiIsArray(env, value));
380     uint32_t length = 0;
381     std::vector<FileHolder> fileHolderVec {};
382     napi_get_array_length(env, value, &length);
383     for (uint32_t i = 0; i < length; i++) {
384         FileHolder fileHolder;
385         napi_value result;
386         napi_get_element(env, value, i, &result);
387         NAPI_BT_CALL_RETURN(NapiParseFileHolder(env, result, fileHolder));
388         fileHolderVec.push_back(fileHolder);
389     }
390     outFileHolderVec = std::move(fileHolderVec);
391     return napi_ok;
392 }
393 
NapiParseFileHolder(napi_env env,napi_value object,FileHolder & outFileHolder)394 napi_status NapiParseFileHolder(napi_env env, napi_value object, FileHolder &outFileHolder)
395 {
396     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"filePath", "fileSize", "fileFd"}));
397     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
398     std::string filePath {};
399     int64_t fileSize = 0;
400     int32_t fileFd = 0;
401     std::string fileType {};
402 
403     NAPI_BT_CALL_RETURN(NapiParseObjectString(env, object, "filePath", filePath));
404     NAPI_BT_CALL_RETURN(NapiParseObjectInt64(env, object, "fileSize", fileSize));
405     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "fileFd", fileFd));
406     HILOGI("fileSize: %{public}" PRId64 "fileFd: %{public}d", fileSize, fileFd);
407 
408     FileHolder fileHolder;
409     fileHolder.filePath = filePath;
410     fileHolder.fileSize = fileSize;
411     fileHolder.fileFd = fileFd;
412     outFileHolder = std::move(fileHolder);
413     return napi_ok;
414 }
415 
416 
NapiParseBdAddr(napi_env env,napi_value value,std::string & outAddr)417 napi_status NapiParseBdAddr(napi_env env, napi_value value, std::string &outAddr)
418 {
419     std::string bdaddr {};
420     NAPI_BT_CALL_RETURN(NapiParseString(env, value, bdaddr));
421     NAPI_BT_RETURN_IF(!IsValidAddress(bdaddr), "Invalid bdaddr", napi_invalid_arg);
422     outAddr = std::move(bdaddr);
423     return napi_ok;
424 }
425 
NapiParseUuid(napi_env env,napi_value value,std::string & outUuid)426 napi_status NapiParseUuid(napi_env env, napi_value value, std::string &outUuid)
427 {
428     std::string uuid {};
429     NAPI_BT_CALL_RETURN(NapiParseString(env, value, uuid));
430     NAPI_BT_RETURN_IF(!IsValidUuid(uuid), "Invalid uuid", napi_invalid_arg);
431     outUuid = std::move(uuid);
432     return napi_ok;
433 }
434 
NapiParseInt64(napi_env env,napi_value value,int64_t & outNum)435 napi_status NapiParseInt64(napi_env env, napi_value value, int64_t &outNum)
436 {
437     int64_t num = 0;
438     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
439     NAPI_BT_CALL_RETURN(napi_get_value_int64(env, value, &num));
440     outNum = num;
441     return napi_ok;
442 }
443 
NapiParseObjectInt64(napi_env env,napi_value object,const char * name,int64_t & outNum)444 napi_status NapiParseObjectInt64(napi_env env, napi_value object, const char *name, int64_t &outNum)
445 {
446     napi_value property;
447     int64_t num = 0;
448     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
449     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
450     NAPI_BT_CALL_RETURN(NapiParseInt64(env, property, num));
451     outNum = num;
452     return napi_ok;
453 }
454 
NapiParseObjectStr(napi_env env,napi_value object,const char * name,std::string & outStr)455 napi_status NapiParseObjectStr(napi_env env, napi_value object, const char *name, std::string &outStr)
456 {
457     napi_value property;
458     std::string str;
459     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
460     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
461     NAPI_BT_CALL_RETURN(NapiParseString(env, property, str));
462     outStr = std::move(str);
463     return napi_ok;
464 }
465 
NapiParseObjectUuids(napi_env env,napi_value object,const char * name,std::vector<std::string> & outUuid)466 napi_status NapiParseObjectUuids(napi_env env, napi_value object, const char *name, std::vector<std::string> &outUuid)
467 {
468     std::string uuids;
469     NAPI_BT_CALL_RETURN(NapiParseObjectStr(env, object, name, uuids));
470     NAPI_BT_CALL_RETURN(ParseAndCheckUuids(uuids, outUuid));
471     return napi_ok;
472 }
473 
ParseAndCheckUuids(const std::string & uuids,std::vector<std::string> & res)474 napi_status ParseAndCheckUuids(const std::string &uuids, std::vector<std::string> &res)
475 {
476     HILOGI("[CLOUD_PAIR] ParseAndCheckUuids %{public}s", uuids.c_str());
477     if (uuids.empty()) {
478         return napi_ok;
479     }
480     const std::regex pattern("[,]");
481     std::vector<std::string> result(
482         std::sregex_token_iterator(uuids.begin(), uuids.end(), pattern, -1),
483         std::sregex_token_iterator()
484     );
485     for (const auto &str : result) {
486         NAPI_BT_RETURN_IF(!IsValidUuid(str), "Invalid uuid", napi_invalid_arg);
487     }
488     res = std::move(result);
489     return napi_ok;
490 }
491 
NapiParseTrustPairDevice(napi_env env,napi_value object,std::vector<TrustPairDeviceParam> & outService)492 napi_status NapiParseTrustPairDevice(napi_env env, napi_value object, std::vector<TrustPairDeviceParam> &outService)
493 {
494     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"trustedPairedDevices"}));
495     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "trustedPairedDevices", outService));
496     return napi_ok;
497 }
498 
NapiParseArrayBuffer(napi_env env,napi_value value,std::vector<uint8_t> & outVec)499 napi_status NapiParseArrayBuffer(napi_env env, napi_value value, std::vector<uint8_t> &outVec)
500 {
501     uint8_t *data = nullptr;
502     size_t size = 0;
503     NAPI_BT_CALL_RETURN(NapiIsArrayBuffer(env, value));
504     bool isSuccess = ParseArrayBuffer(env, &data, size, value);
505     if (!isSuccess) {
506         HILOGE("Parse arraybuffer failed");
507         return napi_invalid_arg;
508     }
509     std::vector<uint8_t> vec(data, data + size);
510     outVec = std::move(vec);
511     return napi_ok;
512 }
513 
NapiParseGattWriteType(napi_env env,napi_value value,int & outWriteType)514 napi_status NapiParseGattWriteType(napi_env env, napi_value value, int &outWriteType)
515 {
516     int writeType = -1;
517     NAPI_BT_CALL_RETURN(NapiParseInt32(env, value, writeType));
518     if (writeType == static_cast<int>(NapiGattWriteType::WRITE)) {
519         HILOGI("gattWriteType: WRITE");
520         outWriteType = GattCharacteristic::WriteType::DEFAULT;
521     } else if (writeType == static_cast<int>(NapiGattWriteType::WRITE_NO_RESPONSE)) {
522         HILOGI("gattWriteType: WRITE_NO_RESPONSE");
523         outWriteType = GattCharacteristic::WriteType::NO_RESPONSE;
524     } else {
525         HILOGE("Invalid gattWriteType: %{public}d", writeType);
526         return napi_invalid_arg;
527     }
528     return napi_ok;
529 }
530 
NapiParseAsyncCallback(napi_env env,napi_callback_info info)531 std::shared_ptr<NapiAsyncCallback> NapiParseAsyncCallback(napi_env env, napi_callback_info info)
532 {
533     size_t argc = ARGS_SIZE_FOUR;
534     napi_value argv[ARGS_SIZE_FOUR] = {nullptr};
535     auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, NULL);
536     if (status != napi_ok) {
537         HILOGE("napi_get_cb_info failed");
538         return nullptr;
539     }
540     if (argc > ARGS_SIZE_FOUR) {
541         HILOGE("size of parameters is larger than ARGS_SIZE_FOUR");
542         return nullptr;
543     }
544 
545     // "argc - 1" is AsyncCallback parameter's index
546     auto asyncCallback = std::make_shared<NapiAsyncCallback>();
547     asyncCallback->env = env;
548     if (argc > 0 && NapiIsFunction(env, argv[argc - 1]) == napi_ok) {
549         HILOGD("callback mode");
550         asyncCallback->callback = std::make_shared<NapiCallback>(env, argv[argc - 1]);
551     } else {
552         HILOGD("promise mode");
553         asyncCallback->promise = std::make_shared<NapiPromise>(env);
554     }
555     return asyncCallback;
556 }
557 
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)558 static napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty,
559     bool &outExist)
560 {
561     bool exist = false;
562     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
563     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &exist));
564     if (exist) {
565         napi_value property;
566         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
567         outProperty = property;
568     }
569     outExist = exist;
570     return napi_ok;
571 }
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty)572 napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty)
573 {
574     bool exist = false;
575     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, outProperty, exist));
576     NAPI_BT_RETURN_IF(!exist, "no needed property", napi_invalid_arg);
577     return napi_ok;
578 }
NapiGetObjectPropertyOptional(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)579 napi_status NapiGetObjectPropertyOptional(napi_env env, napi_value object, const char *name, napi_value &outProperty,
580     bool &outExist)
581 {
582     return NapiGetObjectProperty(env, object, name, outProperty, outExist);
583 }
584 
NapiParseObjectBoolean(napi_env env,napi_value object,const char * name,bool & outBoolean)585 napi_status NapiParseObjectBoolean(napi_env env, napi_value object, const char *name, bool &outBoolean)
586 {
587     napi_value property;
588     bool boolean = true;
589     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
590     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
591     NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
592     outBoolean = boolean;
593     return napi_ok;
594 }
595 
NapiParseObjectUuid(napi_env env,napi_value object,const char * name,std::string & outUuid)596 napi_status NapiParseObjectUuid(napi_env env, napi_value object, const char *name, std::string &outUuid)
597 {
598     napi_value property;
599     std::string uuid {};
600     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
601     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
602     NAPI_BT_CALL_RETURN(NapiParseUuid(env, property, uuid));
603     outUuid = std::move(uuid);
604     return napi_ok;
605 }
606 
NapiParseObjectArrayBuffer(napi_env env,napi_value object,const char * name,std::vector<uint8_t> & outVec)607 napi_status NapiParseObjectArrayBuffer(napi_env env, napi_value object, const char *name, std::vector<uint8_t> &outVec)
608 {
609     napi_value property;
610     std::vector<uint8_t> vec {};
611     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
612     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
613     NAPI_BT_CALL_RETURN(NapiParseArrayBuffer(env, property, vec));
614     outVec = std::move(vec);
615     return napi_ok;
616 }
617 
NapiParseObjectBdAddr(napi_env env,napi_value object,const char * name,std::string & outAddr)618 napi_status NapiParseObjectBdAddr(napi_env env, napi_value object, const char *name, std::string &outAddr)
619 {
620     napi_value property;
621     std::string bdaddr {};
622     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
623     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
624     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, property, bdaddr));
625     outAddr = std::move(bdaddr);
626     return napi_ok;
627 }
628 
NapiParseObjectInt32(napi_env env,napi_value object,const char * name,int32_t & outNum)629 napi_status NapiParseObjectInt32(napi_env env, napi_value object, const char *name, int32_t &outNum)
630 {
631     napi_value property;
632     int32_t num = 0;
633     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
634     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
635     NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
636     outNum = num;
637     return napi_ok;
638 }
639 
NapiParseObjectString(napi_env env,napi_value object,const char * name,std::string & outString)640 napi_status NapiParseObjectString(napi_env env, napi_value object, const char *name, std::string &outString)
641 {
642     napi_value property;
643     std::string str = "";
644     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
645     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
646     NAPI_BT_CALL_RETURN(NapiParseString(env, property, str));
647     outString = str;
648     return napi_ok;
649 }
650 
NapiParseObjectUint32(napi_env env,napi_value object,const char * name,uint32_t & outNum)651 napi_status NapiParseObjectUint32(napi_env env, napi_value object, const char *name, uint32_t &outNum)
652 {
653     napi_value property;
654     uint32_t num = 0;
655     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
656     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
657     NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
658     outNum = num;
659     return napi_ok;
660 }
661 
NapiParseObjectUint32Check(NapiObject napiObject,const char * name,uint32_t & outNum,uint32_t min,uint32_t max)662 napi_status NapiParseObjectUint32Check(NapiObject napiObject, const char *name, uint32_t &outNum,
663     uint32_t min, uint32_t max)
664 {
665     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(napiObject.env, napiObject.object, name, outNum));
666     if (outNum < min || outNum > max) {
667         return napi_invalid_arg;
668     }
669     return napi_ok;
670 }
671 
NapiParseObjectBooleanOptional(napi_env env,napi_value object,const char * name,bool & outBoolean,bool & outExist)672 napi_status NapiParseObjectBooleanOptional(napi_env env, napi_value object, const char *name, bool &outBoolean,
673     bool &outExist)
674 {
675     napi_value property;
676     bool exist = false;
677     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
678     NAPI_BT_CALL_RETURN(NapiGetObjectPropertyOptional(env, object, name, property, exist));
679     if (exist) {
680         bool boolean = true;
681         NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
682         outBoolean = boolean;
683     }
684     outExist = exist;
685     return napi_ok;
686 }
NapiParseObjectInt32Optional(napi_env env,napi_value object,const char * name,int32_t & outNum,bool & outExist)687 napi_status NapiParseObjectInt32Optional(napi_env env, napi_value object, const char *name, int32_t &outNum,
688     bool &outExist)
689 {
690     napi_value property;
691     bool exist = false;
692     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
693     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
694     if (exist) {
695         int32_t num = 0;
696         NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
697         outNum = num;
698     }
699     outExist = exist;
700     return napi_ok;
701 }
NapiParseObjectUint32Optional(napi_env env,napi_value object,const char * name,uint32_t & outNum,bool & outExist)702 napi_status NapiParseObjectUint32Optional(napi_env env, napi_value object, const char *name, uint32_t &outNum,
703     bool &outExist)
704 {
705     napi_value property;
706     bool exist = false;
707     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
708     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
709     if (exist) {
710         uint32_t num = 0;
711         NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
712         outNum = num;
713     }
714     outExist = exist;
715     return napi_ok;
716 }
717 
718 // Parse params template, used for NapiParseArray
719 template <typename T>
NapiParseObject(napi_env env,napi_value object,T & outObj)720 napi_status NapiParseObject(napi_env env, napi_value object, T &outObj)
721 {
722     HILOGE("Unimpleted type");
723     return napi_invalid_arg;
724 }
725 
726 template <>
NapiParseObject(napi_env env,napi_value object,std::string & outObj)727 napi_status NapiParseObject<std::string>(napi_env env, napi_value object, std::string &outObj)
728 {
729     return NapiParseString(env, object, outObj);
730 }
731 
732 template <>
NapiParseObject(napi_env env,napi_value object,UUID & outObj)733 napi_status NapiParseObject<UUID>(napi_env env, napi_value object, UUID &outObj)
734 {
735     std::string uuid {};
736     NAPI_BT_CALL_RETURN(NapiParseUuid(env, object, uuid));
737     outObj = UUID::FromString(uuid);
738     return napi_ok;
739 }
740 
741 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvManufactureData & outObj)742 napi_status NapiParseObject<NapiAdvManufactureData>(napi_env env, napi_value object, NapiAdvManufactureData &outObj)
743 {
744     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"manufactureId", "manufactureValue"}));
745     uint32_t num = 0;
746     std::vector<uint8_t> vec {};
747     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
748     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "manufactureId", num));
749     NAPI_BT_RETURN_IF(num > 0xFFFF, "Invalid manufactureId", napi_invalid_arg);
750     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "manufactureValue", vec));
751 
752     outObj.id = static_cast<uint16_t>(num);
753     outObj.value = std::string(vec.begin(), vec.end());
754     return napi_ok;
755 }
756 
757 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvServiceData & outObj)758 napi_status NapiParseObject<NapiAdvServiceData>(napi_env env, napi_value object, NapiAdvServiceData &outObj)
759 {
760     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "serviceValue"}));
761     std::string uuid {};
762     std::vector<uint8_t> vec {};
763     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
764     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
765     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "serviceValue", vec));
766 
767     outObj.uuid = std::move(uuid);
768     outObj.value = std::move(vec);
769     return napi_ok;
770 }
771 
772 template <>
NapiParseObject(napi_env env,napi_value object,NapiGattService & outObj)773 napi_status NapiParseObject<NapiGattService>(napi_env env, napi_value object, NapiGattService &outObj)
774 {
775     return NapiParseGattService(env, object, outObj);
776 }
777 
778 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleCharacteristic & outObj)779 napi_status NapiParseObject<NapiBleCharacteristic>(napi_env env, napi_value object, NapiBleCharacteristic &outObj)
780 {
781     return NapiParseGattCharacteristic(env, object, outObj);
782 }
783 
784 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleDescriptor & outObj)785 napi_status NapiParseObject<NapiBleDescriptor>(napi_env env, napi_value object, NapiBleDescriptor &outObj)
786 {
787     return NapiParseGattDescriptor(env, object, outObj);
788 }
789 
790 template <>
NapiParseObject(napi_env env,napi_value object,TrustPairDeviceParam & outObj)791 napi_status NapiParseObject<TrustPairDeviceParam>(napi_env env, napi_value object, TrustPairDeviceParam &outObj)
792 {
793     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"sn", "deviceType",
794         "modelId", "manufactory", "productId", "hiLinkVersion", "macAddress", "serviceType",
795         "serviceId", "deviceName", "uuids", "bluetoothClass", "token", "deviceNameTime",
796         "secureAdvertisingInfo", "pairState"}));
797     NapiParseObjectStr(env, object, "sn", outObj.sn_);
798     NapiParseObjectStr(env, object, "deviceType", outObj.deviceType_);
799     NapiParseObjectStr(env, object, "modelId", outObj.modelId_);
800     NapiParseObjectStr(env, object, "manufactory", outObj.manufactory_);
801     NapiParseObjectStr(env, object, "productId", outObj.productId_);
802     NapiParseObjectStr(env, object, "hiLinkVersion", outObj.hiLinkVersion_);
803     NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "macAddress", outObj.macAddress_));
804     NapiParseObjectStr(env, object, "serviceType", outObj.serviceType_);
805     NapiParseObjectStr(env, object, "serviceId", outObj.serviceId_);
806     NapiParseObjectStr(env, object, "deviceName", outObj.deviceName_);
807     NAPI_BT_CALL_RETURN(NapiParseObjectUuids(env, object, "uuids", outObj.uuids_));
808     NapiParseObjectInt32(env, object, "bluetoothClass", outObj.bluetoothClass_);
809     NapiParseObjectInt64(env, object, "deviceNameTime", outObj.deviceNameTime_);
810     NapiParseObjectInt32(env, object, "pairState", outObj.pairState_);
811     std::vector<uint8_t> tokenValue;
812     std::vector<uint8_t> secureAdvertisingInfoValue;
813     NapiParseObjectArrayBuffer(env, object, "token", tokenValue);
814     NapiParseObjectArrayBuffer(env, object, "secureAdvertisingInfo", secureAdvertisingInfoValue);
815     outObj.token_ = std::move(tokenValue);
816     outObj.secureAdvertisingInfo_ = std::move(secureAdvertisingInfoValue);
817     return napi_ok;
818 }
819 
820 template <typename T>
NapiParseArray(napi_env env,napi_value array,std::vector<T> & outVec)821 napi_status NapiParseArray(napi_env env, napi_value array, std::vector<T> &outVec)
822 {
823     std::vector<T> vec {};
824 
825     NAPI_BT_CALL_RETURN(NapiIsArray(env, array));
826     uint32_t length = 0;
827     NAPI_BT_CALL_RETURN(napi_get_array_length(env, array, &length));
828     for (uint32_t i = 0; i < length; ++i) {
829         napi_value element;
830         NAPI_BT_CALL_RETURN(napi_get_element(env, array, i, &element));
831         T object;
832         NAPI_BT_CALL_RETURN(NapiParseObject(env, element, object));
833         vec.push_back(std::move(object));
834     }
835     outVec = std::move(vec);
836     return napi_ok;
837 }
838 // // Declaration, ohters will undefined synbol
839 template napi_status NapiParseArray<NapiBleDescriptor>(napi_env env, napi_value array,
840     std::vector<NapiBleDescriptor> &outVec);
841 template napi_status NapiParseArray<NapiBleCharacteristic>(napi_env env, napi_value array,
842     std::vector<NapiBleCharacteristic> &outVec);
843 template napi_status NapiParseArray<NapiGattService>(napi_env env, napi_value array,
844     std::vector<NapiGattService> &outVec);
845 template napi_status NapiParseArray<NapiAdvServiceData>(napi_env env, napi_value array,
846     std::vector<NapiAdvServiceData> &outVec);
847 template napi_status NapiParseArray<NapiAdvManufactureData>(napi_env env, napi_value array,
848     std::vector<NapiAdvManufactureData> &outVec);
849 template napi_status NapiParseArray<UUID>(napi_env env, napi_value array,
850     std::vector<UUID> &outVec);
851 template napi_status NapiParseArray<std::string>(napi_env env, napi_value array,
852     std::vector<std::string> &outVec);
853 template napi_status NapiParseArray<TrustPairDeviceParam>(napi_env env, napi_value array,
854     std::vector<TrustPairDeviceParam> &outVec);
855 
856 template <typename T>
NapiParseObjectArray(napi_env env,napi_value object,const char * name,std::vector<T> & outVec)857 napi_status NapiParseObjectArray(napi_env env, napi_value object, const char *name, std::vector<T> &outVec)
858 {
859     napi_value property;
860     std::vector<T> vec {};
861     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
862     NAPI_BT_CALL_RETURN(NapiParseArray(env, property, vec));
863     outVec = std::move(vec);
864     return napi_ok;
865 }
866 // Declaration, ohters will undefined synbol
867 template napi_status NapiParseObjectArray<NapiBleDescriptor>(napi_env env, napi_value object, const char *name,
868     std::vector<NapiBleDescriptor> &outVec);
869 template napi_status NapiParseObjectArray<NapiBleCharacteristic>(napi_env env, napi_value object, const char *name,
870     std::vector<NapiBleCharacteristic> &outVec);
871 template napi_status NapiParseObjectArray<NapiGattService>(napi_env env, napi_value object, const char *name,
872     std::vector<NapiGattService> &outVec);
873 template napi_status NapiParseObjectArray<NapiAdvServiceData>(napi_env env, napi_value object, const char *name,
874     std::vector<NapiAdvServiceData> &outVec);
875 template napi_status NapiParseObjectArray<NapiAdvManufactureData>(napi_env env, napi_value object, const char *name,
876     std::vector<NapiAdvManufactureData> &outVec);
877 template napi_status NapiParseObjectArray<UUID>(napi_env env, napi_value object, const char *name,
878     std::vector<UUID> &outVec);
879 template napi_status NapiParseObjectArray<std::string>(napi_env env, napi_value object, const char *name,
880     std::vector<std::string> &outVec);
881 template napi_status NapiParseObjectArray<TrustPairDeviceParam>(napi_env env, napi_value object, const char *name,
882     std::vector<TrustPairDeviceParam> &outVec);
883 }  // namespace Bluetooth
884 }  // namespace OHOS
885