1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "gsm_sms_param_decode.h"
17
18 #include "gsm_pdu_hex_value.h"
19 #include "gsm_sms_common_utils.h"
20 #include "gsm_user_data_pdu.h"
21 #include "securec.h"
22 #include "telephony_log_wrapper.h"
23 #include "text_coder.h"
24
25 namespace OHOS {
26 namespace Telephony {
27 static constexpr uint8_t SLIDE_DATA_STEP = 2;
28 static constexpr uint8_t BCD_TO_DIGITAL = 2;
29
DecodeAddressPdu(SmsReadBuffer & buffer,struct AddressNumber * resultNum)30 bool GsmSmsParamDecode::DecodeAddressPdu(SmsReadBuffer &buffer, struct AddressNumber *resultNum)
31 {
32 if (resultNum == nullptr) {
33 TELEPHONY_LOGE("nullptr error");
34 return false;
35 }
36 if (memset_s(resultNum->address, sizeof(resultNum->address), 0x00, sizeof(resultNum->address)) != EOK) {
37 TELEPHONY_LOGE("memset_s error!");
38 return false;
39 }
40
41 uint8_t oneByte = 0;
42 if (!buffer.ReadByte(oneByte) || oneByte >= BCD_TO_DIGITAL * (MAX_ADDRESS_LEN + 1)) {
43 TELEPHONY_LOGE("get data error. %{public}d", oneByte);
44 return false;
45 }
46 uint8_t addrLen = oneByte;
47 uint8_t bcdLen = 0;
48 if (addrLen % SLIDE_DATA_STEP == 0) {
49 bcdLen = addrLen / SLIDE_DATA_STEP;
50 } else {
51 bcdLen = addrLen / SLIDE_DATA_STEP + 1;
52 }
53
54 if (!buffer.PickOneByte(oneByte)) {
55 TELEPHONY_LOGE("get data error.");
56 return false;
57 }
58 resultNum->ton = (oneByte & HEX_VALUE_70) >> HEX_VALUE_04;
59
60 if (resultNum->ton == TYPE_ALPHA_NUMERIC) {
61 return DecodeAddressAlphaNum(buffer, resultNum, bcdLen, addrLen);
62 } else if (resultNum->ton == TYPE_INTERNATIONAL) {
63 return DecodeAddressInternationalNum(buffer, resultNum, bcdLen);
64 } else {
65 return DecodeAddressDefaultNum(buffer, resultNum, bcdLen);
66 }
67 }
68
DecodeAddressAlphaNum(SmsReadBuffer & buffer,struct AddressNumber * resultNum,uint8_t bcdLen,uint8_t addrLen)69 bool GsmSmsParamDecode::DecodeAddressAlphaNum(
70 SmsReadBuffer &buffer, struct AddressNumber *resultNum, uint8_t bcdLen, uint8_t addrLen)
71 {
72 uint8_t tmresultNum[MAX_ADDRESS_LEN] = { 0 };
73 uint8_t dataLen = (addrLen * HEX_VALUE_04) / HEX_VALUE_07;
74 TELEPHONY_LOGI("DecodeAddressAlphaNum, addrLen:%{public}d, dataLen: %{public}d", addrLen, dataLen);
75 uint8_t addressPduArr[MAX_ADDRESS_LEN + 1] = { 0 };
76 uint8_t oneByte = 0;
77 if (!buffer.ReadByte(oneByte)) {
78 TELEPHONY_LOGE("get data error.");
79 return false;
80 }
81 uint32_t encodeLen = (addrLen % HEX_VALUE_02 == 0) ? (addrLen / HEX_VALUE_02) :
82 (addrLen / HEX_VALUE_02 + HEX_VALUE_01);
83 TELEPHONY_LOGI("DecodeAddressAlphaNum, encodeLen %{public}d", encodeLen);
84 for (uint8_t i = 0; i < encodeLen; i++) {
85 if (!buffer.ReadByte(oneByte)) {
86 TELEPHONY_LOGE("get data error.");
87 return false;
88 }
89 addressPduArr[i] = oneByte;
90 }
91 if (!GsmSmsCommonUtils::Unpack7bitCharForMiddlePart(addressPduArr, dataLen, tmresultNum)) {
92 TELEPHONY_LOGE("unpack 7bit char error!");
93 return false;
94 }
95 MsgLangInfo langInfo;
96 langInfo.bSingleShift = false;
97 langInfo.bLockingShift = false;
98 TextCoder::Instance().Gsm7bitToUtf8(
99 reinterpret_cast<uint8_t *>(resultNum->address), MAX_ADDRESS_LEN, tmresultNum, dataLen, langInfo);
100 return true;
101 }
102
DecodeAddressInternationalNum(SmsReadBuffer & buffer,struct AddressNumber * resultNum,uint8_t bcdLen)103 bool GsmSmsParamDecode::DecodeAddressInternationalNum(
104 SmsReadBuffer &buffer, struct AddressNumber *resultNum, uint8_t bcdLen)
105 {
106 buffer.MoveForward(1);
107 uint8_t oneByte = 0;
108 uint8_t index = 0;
109 uint8_t bcdArr[MAX_ADDRESS_LEN + 1] = { 0 };
110 while (index < bcdLen && index < MAX_ADDRESS_LEN) {
111 if (!buffer.ReadByte(oneByte)) {
112 TELEPHONY_LOGE("get data error.");
113 return false;
114 }
115 bcdArr[index++] = oneByte;
116 }
117
118 GsmSmsCommonUtils utils;
119 std::string addrNum;
120 if (!utils.BcdToDigit(bcdArr, bcdLen, addrNum, SMS_MAX_ADDRESS_LEN)) {
121 TELEPHONY_LOGE("BcdToDigit fail!");
122 return false;
123 }
124 for (uint8_t i = 0; i < addrNum.size() && i < MAX_ADDRESS_LEN; i++) {
125 resultNum->address[i + 1] = addrNum[i];
126 }
127
128 if (resultNum->address[1] != '\0') {
129 resultNum->address[0] = '+';
130 }
131 return true;
132 }
133
DecodeAddressDefaultNum(SmsReadBuffer & buffer,struct AddressNumber * resultNum,uint8_t bcdLen)134 bool GsmSmsParamDecode::DecodeAddressDefaultNum(SmsReadBuffer &buffer, struct AddressNumber *resultNum, uint8_t bcdLen)
135 {
136 uint8_t index = 0;
137 buffer.MoveForward(1);
138 uint8_t oneByte = 0;
139 uint8_t bcdArr[MAX_ADDRESS_LEN + 1] = { 0 };
140 while (index < bcdLen && index < MAX_ADDRESS_LEN) {
141 if (!buffer.ReadByte(oneByte)) {
142 TELEPHONY_LOGE("get data error.");
143 return false;
144 }
145 bcdArr[index++] = oneByte;
146 }
147 GsmSmsCommonUtils utils;
148 std::string addrNum;
149 if (!utils.BcdToDigit(bcdArr, bcdLen, addrNum, SMS_MAX_ADDRESS_LEN)) {
150 TELEPHONY_LOGE("BcdToDigit fail!");
151 return false;
152 }
153 for (uint8_t i = 0; i < addrNum.size() && i < MAX_ADDRESS_LEN; i++) {
154 resultNum->address[i] = addrNum[i];
155 }
156 return true;
157 }
158
DecodeSmscPdu(uint8_t * srcAddr,uint8_t addrLen,enum TypeOfNum ton,std::string & desAddr)159 void GsmSmsParamDecode::DecodeSmscPdu(uint8_t *srcAddr, uint8_t addrLen, enum TypeOfNum ton, std::string &desAddr)
160 {
161 if (srcAddr == nullptr || addrLen == 0) {
162 TELEPHONY_LOGE("smsc data error.");
163 return;
164 }
165
166 GsmSmsCommonUtils utils;
167 if (ton == TYPE_INTERNATIONAL) {
168 desAddr[0] = '+';
169 if (!utils.BcdToDigit(srcAddr, addrLen, desAddr, SMS_MAX_ADDRESS_LEN)) {
170 TELEPHONY_LOGE("BcdToDigit fail!");
171 return;
172 }
173 } else {
174 if (!utils.BcdToDigit(srcAddr, addrLen, desAddr, SMS_MAX_ADDRESS_LEN)) {
175 TELEPHONY_LOGE("BcdToDigit fail!");
176 return;
177 }
178 }
179 }
180
DecodeSmscPdu(const uint8_t * pTpdu,uint8_t pduLen,struct AddressNumber & desAddrObj)181 uint8_t GsmSmsParamDecode::DecodeSmscPdu(const uint8_t *pTpdu, uint8_t pduLen, struct AddressNumber &desAddrObj)
182 {
183 if (pTpdu == nullptr || pduLen == 0) {
184 TELEPHONY_LOGE("nullptr error.");
185 return 0;
186 }
187 if (memset_s(desAddrObj.address, sizeof(desAddrObj.address), 0x00, sizeof(desAddrObj.address)) != EOK) {
188 TELEPHONY_LOGE("memset_s error!");
189 return 0;
190 }
191
192 uint8_t offset = 0;
193 uint8_t addrLen = pTpdu[offset++];
194 if (addrLen == 0) {
195 TELEPHONY_LOGI("smsc is 00.");
196 return offset;
197 }
198 if (addrLen >= pduLen || offset >= pduLen) {
199 TELEPHONY_LOGI("smsc absent.");
200 return 0;
201 }
202 desAddrObj.ton = (pTpdu[offset] & HEX_VALUE_70) >> HEX_VALUE_04;
203 desAddrObj.npi = pTpdu[offset++] & HEX_VALUE_0F;
204
205 GsmSmsCommonUtils utils;
206 if (desAddrObj.ton == TYPE_INTERNATIONAL) {
207 if (addrLen > SMS_MAX_ADDRESS_LEN || (offset + addrLen) >= pduLen) {
208 TELEPHONY_LOGE("addrLen invalid.");
209 return 0;
210 }
211 std::string addrNum;
212 utils.BcdToDigit(&(pTpdu[offset]), addrLen, addrNum, SMS_MAX_ADDRESS_LEN);
213 for (uint8_t i = 0; i < addrNum.size() && i < MAX_ADDRESS_LEN; i++) {
214 desAddrObj.address[i + 1] = addrNum[i];
215 }
216 if (desAddrObj.address[1] != '\0') {
217 desAddrObj.address[0] = '+';
218 }
219 } else {
220 if (addrLen > SMS_MAX_ADDRESS_LEN || (offset + addrLen) >= pduLen) {
221 TELEPHONY_LOGE("addrLen invalid.");
222 return 0;
223 }
224 std::string addrNum;
225 utils.BcdToDigit(&(pTpdu[offset]), addrLen, addrNum, SMS_MAX_ADDRESS_LEN);
226 for (uint8_t i = 0; i < addrNum.size() && i < MAX_ADDRESS_LEN; i++) {
227 desAddrObj.address[i] = addrNum[i];
228 }
229 }
230
231 offset += (addrLen - 1);
232 return offset;
233 }
234
DecodeDcsPdu(SmsReadBuffer & buffer,struct SmsDcs * smsDcs)235 bool GsmSmsParamDecode::DecodeDcsPdu(SmsReadBuffer &buffer, struct SmsDcs *smsDcs)
236 {
237 if (smsDcs == nullptr) {
238 TELEPHONY_LOGE("smsDcs nullptr.");
239 return false;
240 }
241 uint8_t dcs = 0;
242 if (!buffer.ReadByte(dcs)) {
243 TELEPHONY_LOGE("get data error.");
244 return false;
245 }
246
247 smsDcs->bMWI = false;
248 smsDcs->bIndActive = false;
249 smsDcs->indType = SMS_OTHER_INDICATOR;
250 if (((dcs & HEX_VALUE_C0) >> HEX_VALUE_06) == 0) {
251 DecodeDcsGeneralGroupPdu(dcs, smsDcs);
252 } else if (((dcs & HEX_VALUE_F0) >> HEX_VALUE_04) == HEX_VALUE_0F) {
253 DecodeDcsClassGroupPdu(dcs, smsDcs);
254 } else if (((dcs & HEX_VALUE_C0) >> HEX_VALUE_06) == HEX_VALUE_01) {
255 DecodeDcsDeleteGroupPdu(dcs, smsDcs);
256 } else if (((dcs & HEX_VALUE_F0) >> HEX_VALUE_04) == HEX_VALUE_0C) {
257 DecodeDcsDiscardGroupPdu(dcs, smsDcs);
258 } else if (((dcs & HEX_VALUE_F0) >> HEX_VALUE_04) == HEX_VALUE_0D) {
259 DecodeDcsStoreGsmGroupPdu(dcs, smsDcs);
260 } else if (((dcs & HEX_VALUE_F0) >> HEX_VALUE_04) == HEX_VALUE_0E) {
261 DecodeDcsStoreUCS2GroupPdu(dcs, smsDcs);
262 } else {
263 DecodeDcsUnknownGroupPdu(dcs, smsDcs);
264 }
265 return true;
266 }
267
DecodeDcsGeneralGroupPdu(uint8_t dcs,struct SmsDcs * smsDcs)268 void GsmSmsParamDecode::DecodeDcsGeneralGroupPdu(uint8_t dcs, struct SmsDcs *smsDcs)
269 {
270 if (smsDcs == nullptr) {
271 TELEPHONY_LOGE("smsDcs is nullptr.");
272 return;
273 }
274
275 smsDcs->codingGroup = CODING_GENERAL_GROUP;
276 smsDcs->bCompressed = (dcs & HEX_VALUE_20) >> HEX_VALUE_05;
277 smsDcs->codingScheme = GetMsgCodingScheme((dcs & HEX_VALUE_0C) >> HEX_VALUE_02);
278 if (((dcs & HEX_VALUE_10) >> HEX_VALUE_04) == 0) {
279 smsDcs->msgClass = SMS_CLASS_UNKNOWN;
280 } else {
281 smsDcs->msgClass = GetMsgClass(dcs & HEX_VALUE_03);
282 }
283 }
284
DecodeDcsClassGroupPdu(uint8_t dcs,struct SmsDcs * smsDcs)285 void GsmSmsParamDecode::DecodeDcsClassGroupPdu(uint8_t dcs, struct SmsDcs *smsDcs)
286 {
287 if (smsDcs == nullptr) {
288 TELEPHONY_LOGE("smsDcs is nullptr.");
289 return;
290 }
291
292 smsDcs->codingGroup = SMS_CLASS_GROUP;
293 smsDcs->bCompressed = false;
294 smsDcs->codingScheme = GetMsgCodingScheme((dcs & HEX_VALUE_0C) >> HEX_VALUE_02);
295 smsDcs->msgClass = GetMsgClass(dcs & HEX_VALUE_03);
296 }
297
DecodeDcsDeleteGroupPdu(uint8_t dcs,struct SmsDcs * smsDcs)298 void GsmSmsParamDecode::DecodeDcsDeleteGroupPdu(uint8_t dcs, struct SmsDcs *smsDcs)
299 {
300 if (smsDcs == nullptr) {
301 TELEPHONY_LOGE("smsDcs is nullptr.");
302 return;
303 }
304
305 smsDcs->codingGroup = CODING_DELETION_GROUP;
306 smsDcs->bCompressed = false;
307 smsDcs->msgClass = SMS_CLASS_UNKNOWN;
308 }
309
DecodeDcsDiscardGroupPdu(uint8_t dcs,struct SmsDcs * smsDcs)310 void GsmSmsParamDecode::DecodeDcsDiscardGroupPdu(uint8_t dcs, struct SmsDcs *smsDcs)
311 {
312 if (smsDcs == nullptr) {
313 TELEPHONY_LOGE("smsDcs is null.");
314 return;
315 }
316
317 smsDcs->codingGroup = CODING_DISCARD_GROUP;
318 GetMwiType(dcs, *smsDcs);
319 }
320
DecodeDcsStoreGsmGroupPdu(uint8_t dcs,struct SmsDcs * smsDcs)321 void GsmSmsParamDecode::DecodeDcsStoreGsmGroupPdu(uint8_t dcs, struct SmsDcs *smsDcs)
322 {
323 if (smsDcs == nullptr) {
324 TELEPHONY_LOGE("smsDcs is null.");
325 return;
326 }
327
328 smsDcs->codingGroup = CODING_STORE_GROUP;
329 smsDcs->codingScheme = DATA_CODING_7BIT;
330 GetMwiType(dcs, *smsDcs);
331 }
332
DecodeDcsStoreUCS2GroupPdu(uint8_t dcs,struct SmsDcs * smsDcs)333 void GsmSmsParamDecode::DecodeDcsStoreUCS2GroupPdu(uint8_t dcs, struct SmsDcs *smsDcs)
334 {
335 if (smsDcs == nullptr) {
336 TELEPHONY_LOGE("smsDcs is null.");
337 return;
338 }
339
340 smsDcs->codingGroup = CODING_STORE_GROUP;
341 smsDcs->codingScheme = DATA_CODING_UCS2;
342 GetMwiType(dcs, *smsDcs);
343 }
344
DecodeDcsUnknownGroupPdu(uint8_t dcs,struct SmsDcs * smsDcs)345 void GsmSmsParamDecode::DecodeDcsUnknownGroupPdu(uint8_t dcs, struct SmsDcs *smsDcs)
346 {
347 if (smsDcs == nullptr) {
348 TELEPHONY_LOGE("smsDcs is null.");
349 return;
350 }
351
352 smsDcs->codingGroup = CODING_UNKNOWN_GROUP;
353 smsDcs->bCompressed = (dcs & HEX_VALUE_20) >> HEX_VALUE_05;
354 smsDcs->codingScheme = GetMsgCodingScheme((dcs & HEX_VALUE_0C) >> HEX_VALUE_02);
355 smsDcs->msgClass = SMS_CLASS_UNKNOWN;
356 }
357
GetMsgClass(uint8_t dcs)358 enum SmsMessageClass GsmSmsParamDecode::GetMsgClass(uint8_t dcs)
359 {
360 return (enum SmsMessageClass)(dcs & HEX_VALUE_03);
361 }
362
GetMsgCodingScheme(uint8_t dcs)363 enum DataCodingScheme GsmSmsParamDecode::GetMsgCodingScheme(uint8_t dcs)
364 {
365 return (enum DataCodingScheme)(dcs & HEX_VALUE_03);
366 }
367
GetMsgIndicatorType(const uint8_t dcs)368 enum SmsIndicatorType GsmSmsParamDecode::GetMsgIndicatorType(const uint8_t dcs)
369 {
370 return (enum SmsIndicatorType)(dcs & HEX_VALUE_03);
371 }
372
GetMwiType(const uint8_t dcs,struct SmsDcs & smsDcs)373 void GsmSmsParamDecode::GetMwiType(const uint8_t dcs, struct SmsDcs &smsDcs)
374 {
375 smsDcs.bCompressed = false;
376 smsDcs.msgClass = SMS_CLASS_UNKNOWN;
377 smsDcs.bMWI = true;
378 smsDcs.bIndActive = (((dcs & HEX_VALUE_08) >> HEX_VALUE_03) == HEX_VALUE_01) ? true : false;
379 smsDcs.indType = GetMsgIndicatorType(dcs & HEX_VALUE_03);
380 }
381
DecodeTimePdu(SmsReadBuffer & buffer,struct SmsTimeStamp * timeStamp)382 bool GsmSmsParamDecode::DecodeTimePdu(SmsReadBuffer &buffer, struct SmsTimeStamp *timeStamp)
383 {
384 if (timeStamp == nullptr) {
385 TELEPHONY_LOGE("nullptr error.");
386 return false;
387 }
388 /* decode in ABSOLUTE time type. */
389 timeStamp->format = SMS_TIME_ABSOLUTE;
390
391 uint8_t pickByte = 0;
392 if (!buffer.PickOneByte(pickByte)) {
393 TELEPHONY_LOGE("get data error.");
394 return false;
395 }
396 uint8_t oneByte = 0;
397 if (!buffer.ReadByte(oneByte)) {
398 TELEPHONY_LOGE("get data error.");
399 return false;
400 }
401
402 timeStamp->time.absolute.year =
403 (pickByte & HEX_VALUE_0F) * HEX_VALUE_0A + ((oneByte & HEX_VALUE_F0) >> HEX_VALUE_04);
404
405 if (!buffer.PickOneByte(pickByte)) {
406 TELEPHONY_LOGE("get data error.");
407 return false;
408 }
409 if (!buffer.ReadByte(oneByte)) {
410 TELEPHONY_LOGE("get data error.");
411 return false;
412 }
413 timeStamp->time.absolute.month =
414 (pickByte & HEX_VALUE_0F) * HEX_VALUE_0A + ((oneByte & HEX_VALUE_F0) >> HEX_VALUE_04);
415 return DecodeTimePduPartData(buffer, timeStamp);
416 }
417
DecodeTimePduPartData(SmsReadBuffer & buffer,struct SmsTimeStamp * timeStamp)418 bool GsmSmsParamDecode::DecodeTimePduPartData(SmsReadBuffer &buffer, struct SmsTimeStamp *timeStamp)
419 {
420 uint8_t pickByte = 0;
421 if (!buffer.PickOneByte(pickByte)) {
422 TELEPHONY_LOGE("get data error.");
423 return false;
424 }
425
426 uint8_t oneByte = 0;
427 if (!buffer.ReadByte(oneByte)) {
428 TELEPHONY_LOGE("get data error.");
429 return false;
430 }
431 timeStamp->time.absolute.day =
432 (pickByte & HEX_VALUE_0F) * HEX_VALUE_0A + ((oneByte & HEX_VALUE_F0) >> HEX_VALUE_04);
433
434 if (!buffer.PickOneByte(pickByte)) {
435 TELEPHONY_LOGE("get data error.");
436 return false;
437 }
438 if (!buffer.ReadByte(oneByte)) {
439 TELEPHONY_LOGE("get data error.");
440 return false;
441 }
442 timeStamp->time.absolute.hour =
443 (pickByte & HEX_VALUE_0F) * HEX_VALUE_0A + ((oneByte & HEX_VALUE_F0) >> HEX_VALUE_04);
444
445 if (!buffer.PickOneByte(pickByte)) {
446 TELEPHONY_LOGE("get data error.");
447 return false;
448 }
449 if (!buffer.ReadByte(oneByte)) {
450 TELEPHONY_LOGE("get data error.");
451 return false;
452 }
453 timeStamp->time.absolute.minute =
454 (pickByte & HEX_VALUE_0F) * HEX_VALUE_0A + ((oneByte & HEX_VALUE_F0) >> HEX_VALUE_04);
455 return DecodeTimePduData(buffer, timeStamp);
456 }
457
DecodeTimePduData(SmsReadBuffer & buffer,struct SmsTimeStamp * timeStamp)458 bool GsmSmsParamDecode::DecodeTimePduData(SmsReadBuffer &buffer, struct SmsTimeStamp *timeStamp)
459 {
460 if (timeStamp == nullptr) {
461 TELEPHONY_LOGE("nullptr error.");
462 return false;
463 }
464
465 uint8_t pickByte = 0;
466 if (!buffer.PickOneByte(pickByte)) {
467 TELEPHONY_LOGE("get data error.");
468 return false;
469 }
470
471 uint8_t oneByte = 0;
472 if (!buffer.ReadByte(oneByte)) {
473 TELEPHONY_LOGE("get data error.");
474 return false;
475 }
476 timeStamp->time.absolute.second =
477 (pickByte & HEX_VALUE_0F) * HEX_VALUE_10 + ((oneByte & HEX_VALUE_F0) >> HEX_VALUE_04);
478
479 if (!buffer.PickOneByte(pickByte)) {
480 TELEPHONY_LOGE("get data error.");
481 return false;
482 }
483 if (!buffer.PickOneByte(oneByte)) {
484 TELEPHONY_LOGE("get data error.");
485 return false;
486 }
487 timeStamp->time.absolute.timeZone =
488 (pickByte & HEX_VALUE_07) * HEX_VALUE_10 + ((oneByte & HEX_VALUE_F0) >> HEX_VALUE_04);
489
490 if (!buffer.ReadByte(oneByte)) {
491 TELEPHONY_LOGE("get data error.");
492 return false;
493 }
494 if (oneByte & HEX_VALUE_08) {
495 timeStamp->time.absolute.timeZone *= (-1);
496 }
497 return true;
498 }
499 } // namespace Telephony
500 } // namespace OHOS
501