1 /*
2 * Copyright (C) 2021-2024 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 "multi_sim_monitor.h"
17
18 #include <atomic>
19
20 #include "common_event_manager.h"
21 #include "common_event_support.h"
22 #include "os_account_manager_wrapper.h"
23 #include "operator_file_parser.h"
24 #include "radio_event.h"
25 #include "string_ex.h"
26 #include "telephony_errors.h"
27 #include "telephony_ext_wrapper.h"
28
29 namespace OHOS {
30 namespace Telephony {
31 const int64_t DELAY_TIME = 1000;
32 const int INIT_TIMES = 15;
33 const int INIT_DATA_TIMES = 5;
MultiSimMonitor(const std::shared_ptr<MultiSimController> & controller,std::vector<std::shared_ptr<Telephony::SimStateManager>> simStateManager,std::vector<std::weak_ptr<Telephony::SimFileManager>> simFileManager)34 MultiSimMonitor::MultiSimMonitor(const std::shared_ptr<MultiSimController> &controller,
35 std::vector<std::shared_ptr<Telephony::SimStateManager>> simStateManager,
36 std::vector<std::weak_ptr<Telephony::SimFileManager>> simFileManager)
37 : TelEventHandler("MultiSimMonitor"), controller_(controller), simStateManager_(simStateManager),
38 simFileManager_(simFileManager)
39 {
40 if (observerHandler_ == nullptr) {
41 observerHandler_ = std::make_unique<ObserverHandler>();
42 }
43 }
44
~MultiSimMonitor()45 MultiSimMonitor::~MultiSimMonitor()
46 {
47 TELEPHONY_LOGD("destory");
48 UnSubscribeListeners();
49 }
50
Init()51 void MultiSimMonitor::Init()
52 {
53 TELEPHONY_LOGD("init");
54 isSimAccountLoaded_.resize(SIM_SLOT_COUNT, 0);
55 initDataRemainCount_.resize(SIM_SLOT_COUNT, INIT_DATA_TIMES);
56 SendEvent(MultiSimMonitor::REGISTER_SIM_NOTIFY_EVENT);
57 InitListener();
58 }
59
AddExtraManagers(std::shared_ptr<Telephony::SimStateManager> simStateManager,std::shared_ptr<Telephony::SimFileManager> simFileManager)60 void MultiSimMonitor::AddExtraManagers(std::shared_ptr<Telephony::SimStateManager> simStateManager,
61 std::shared_ptr<Telephony::SimFileManager> simFileManager)
62 {
63 if (static_cast<int32_t>(simStateManager_.size()) == SIM_SLOT_COUNT) {
64 simStateManager_.push_back(simStateManager);
65 simFileManager_.push_back(simFileManager);
66 isSimAccountLoaded_.push_back(0);
67 initDataRemainCount_.push_back(INIT_DATA_TIMES);
68 RegisterSimNotify(SIM_SLOT_2);
69 }
70 }
71
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)72 void MultiSimMonitor::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
73 {
74 if (event == nullptr) {
75 TELEPHONY_LOGE("start ProcessEvent but event is null!");
76 return;
77 }
78 auto eventCode = event->GetInnerEventId();
79 TELEPHONY_LOGI("eventCode is %{public}d", eventCode);
80 switch (eventCode) {
81 case MultiSimMonitor::INIT_DATA_RETRY_EVENT:{
82 auto slotId = event->GetParam();
83 InitData(slotId);
84 break;
85 }
86 case RadioEvent::RADIO_QUERY_ICCID_DONE:
87 case RadioEvent::RADIO_SIM_STATE_LOCKED:
88 case RadioEvent::RADIO_SIM_STATE_READY: {
89 RemoveEvent(MultiSimMonitor::INIT_DATA_RETRY_EVENT);
90 auto slotId = event->GetParam();
91 InitData(slotId);
92 break;
93 }
94 case RadioEvent::RADIO_SIM_STATE_CHANGE: {
95 auto slotId = event->GetParam();
96 RefreshData(slotId);
97 break;
98 }
99 case MultiSimMonitor::REGISTER_SIM_NOTIFY_EVENT: {
100 RemoveEvent(MultiSimMonitor::REGISTER_SIM_NOTIFY_RETRY_EVENT);
101 RegisterSimNotify();
102 break;
103 }
104 case MultiSimMonitor::REGISTER_SIM_NOTIFY_RETRY_EVENT: {
105 RegisterSimNotify();
106 break;
107 }
108 case MultiSimMonitor::RESET_OPKEY_CONFIG: {
109 ClearAllOpcCache();
110 UpdateAllOpkeyConfigs();
111 break;
112 }
113 default:
114 break;
115 }
116 }
117
CheckOpcNeedUpdata(const bool isDataShareError)118 void MultiSimMonitor::CheckOpcNeedUpdata(const bool isDataShareError)
119 {
120 TelFFRTUtils::Submit([=]() {
121 bool isOpcVersionUpdated = CheckUpdateOpcVersion() == TELEPHONY_SUCCESS;
122 if (isOpcVersionUpdated) {
123 OperatorFileParser::ClearFilesCache();
124 }
125 TELEPHONY_LOGI("CheckOpcNeedUpdata isDataShareError: %{public}d, isOpcVersionUpdated: %{public}d",
126 isDataShareError, isOpcVersionUpdated);
127 if (isOpcVersionUpdated || isDataShareError) {
128 SendEvent(MultiSimMonitor::RESET_OPKEY_CONFIG);
129 }
130 });
131 }
132
CheckUpdateOpcVersion()133 int32_t MultiSimMonitor::CheckUpdateOpcVersion()
134 {
135 if (TELEPHONY_EXT_WRAPPER.checkOpcVersionIsUpdate_ != nullptr &&
136 TELEPHONY_EXT_WRAPPER.updateOpcVersion_ != nullptr) {
137 std::lock_guard<std::mutex> lock(mutexForData_);
138 if (TELEPHONY_EXT_WRAPPER.checkOpcVersionIsUpdate_()) {
139 TELEPHONY_LOGI("need update config");
140 if (controller_->UpdateOpKeyInfo() != TELEPHONY_SUCCESS) {
141 TELEPHONY_LOGW("UpdateOpKeyInfo error");
142 return TELEPHONY_ERROR;
143 }
144 TELEPHONY_EXT_WRAPPER.updateOpcVersion_();
145 TELEPHONY_LOGI("Version updated succ");
146 return TELEPHONY_SUCCESS;
147 }
148 }
149 return TELEPHONY_ERROR;
150 }
151
ClearAllOpcCache()152 void MultiSimMonitor::ClearAllOpcCache()
153 {
154 for (size_t slotId = 0; slotId < simFileManager_.size(); slotId++) {
155 auto simFileManager = simFileManager_[slotId].lock();
156 if (simFileManager == nullptr) {
157 TELEPHONY_LOGE("simFileManager is nullptr, slotId : %{public}zu", slotId);
158 continue;
159 }
160 simFileManager->DeleteOperatorCache();
161 }
162 }
163
UpdateAllOpkeyConfigs()164 void MultiSimMonitor::UpdateAllOpkeyConfigs()
165 {
166 for (size_t slotId = 0; slotId < simFileManager_.size(); slotId++) {
167 auto simFileManager = simFileManager_[slotId].lock();
168 if (simFileManager == nullptr) {
169 TELEPHONY_LOGE("simFileManager is nullptr, slotId : %{public}zu", slotId);
170 continue;
171 }
172 simFileManager->UpdateOpkeyConfig();
173 }
174 }
175
InitData(int32_t slotId)176 void MultiSimMonitor::InitData(int32_t slotId)
177 {
178 TELEPHONY_LOGI("MultiSimMonitor::InitData slotId = %{public}d", slotId);
179 if (!IsValidSlotId(slotId)) {
180 TELEPHONY_LOGE("MultiSimMonitor::InitData slotId is invalid");
181 return;
182 }
183 if (isSimAccountLoaded_[slotId]) {
184 TELEPHONY_LOGI("MultiSimMonitor::InitData simAccountInfo is already loaded");
185 return;
186 }
187 if (controller_ == nullptr) {
188 TELEPHONY_LOGE("MultiSimMonitor::InitData controller_ is nullptr");
189 return;
190 }
191 if (!controller_->InitData(slotId)) {
192 TELEPHONY_LOGE("MultiSimMonitor::InitData failed");
193 if (initDataRemainCount_[slotId] > 0) {
194 SendEvent(MultiSimMonitor::INIT_DATA_RETRY_EVENT, slotId, DELAY_TIME);
195 TELEPHONY_LOGI("retry remain %{public}d", initDataRemainCount_[slotId]);
196 initDataRemainCount_[slotId]--;
197 }
198 return;
199 }
200 isSimAccountLoaded_[slotId] = 1;
201 if (observerHandler_ == nullptr) {
202 TELEPHONY_LOGE("MultiSimMonitor::InitData observerHandler_ is nullptr");
203 return;
204 }
205 NotifySimAccountChanged();
206 observerHandler_->NotifyObserver(RadioEvent::RADIO_SIM_ACCOUNT_LOADED, slotId);
207 }
208
RefreshData(int32_t slotId)209 void MultiSimMonitor::RefreshData(int32_t slotId)
210 {
211 if (!IsValidSlotId(slotId)) {
212 TELEPHONY_LOGE("MultiSimMonitor::RefreshData slotId is invalid");
213 return;
214 }
215 auto simFileManager = simFileManager_[slotId].lock();
216 if (controller_ == nullptr || simStateManager_[slotId] == nullptr || simFileManager == nullptr) {
217 TELEPHONY_LOGE("MultiSimMonitor::RefreshData controller_ or simStateManager_ is nullptr");
218 return;
219 }
220 if (simStateManager_[slotId]->GetSimState() == SimState::SIM_STATE_NOT_PRESENT) {
221 TELEPHONY_LOGI("MultiSimMonitor::RefreshData clear data when sim is absent");
222 controller_->ForgetAllData(slotId);
223 controller_->GetListFromDataBase();
224 isSimAccountLoaded_[slotId] = 0;
225 initDataRemainCount_[slotId] = INIT_DATA_TIMES;
226 simFileManager->ClearData();
227 } else if (simStateManager_[slotId]->GetSimState() == SimState::SIM_STATE_UNKNOWN) {
228 TELEPHONY_LOGI("MultiSimMonitor::RefreshData clear data when sim is unknown");
229 simFileManager->ClearData();
230 }
231 if (controller_->unInitModemSlotId_ == slotId) {
232 TELEPHONY_LOGI("need to recheck primary");
233 controller_->ReCheckPrimary();
234 }
235 NotifySimAccountChanged();
236 }
237
RegisterCoreNotify(int32_t slotId,const std::shared_ptr<AppExecFwk::EventHandler> & handler,int what)238 void MultiSimMonitor::RegisterCoreNotify(
239 int32_t slotId, const std::shared_ptr<AppExecFwk::EventHandler> &handler, int what)
240 {
241 if (observerHandler_ == nullptr || handler == nullptr) {
242 TELEPHONY_LOGE("observerHandler_ or handler is nullptr");
243 return;
244 }
245 observerHandler_->RegObserver(what, handler);
246 if (!IsValidSlotId(slotId)) {
247 TELEPHONY_LOGE("MultiSimMonitor::RegisterCoreNotify slotId is invalid");
248 return;
249 }
250 if (isSimAccountLoaded_[slotId] || IsVSimSlotId(slotId)) {
251 TELEPHONY_LOGI("notify slotId:%{public}d sim account loaded", slotId);
252 TelEventHandler::SendTelEvent(handler, RadioEvent::RADIO_SIM_ACCOUNT_LOADED, slotId, 0);
253 }
254 }
255
IsValidSlotId(int32_t slotId)256 bool MultiSimMonitor::IsValidSlotId(int32_t slotId)
257 {
258 return (slotId >= DEFAULT_SIM_SLOT_ID) && slotId < static_cast<int32_t>(simStateManager_.size());
259 }
260
IsVSimSlotId(int32_t slotId)261 bool MultiSimMonitor::IsVSimSlotId(int32_t slotId)
262 {
263 if (TELEPHONY_EXT_WRAPPER.getVSimSlotId_) {
264 int vSimSlotId = DEFAULT_SIM_SLOT_ID_REMOVE;
265 TELEPHONY_EXT_WRAPPER.getVSimSlotId_(vSimSlotId);
266 return vSimSlotId == slotId;
267 }
268 return false;
269 }
270
UnSubscribeListeners()271 void MultiSimMonitor::UnSubscribeListeners()
272 {
273 if (dataShareSubscriber_ != nullptr && CommonEventManager::UnSubscribeCommonEvent(dataShareSubscriber_)) {
274 dataShareSubscriber_ = nullptr;
275 TELEPHONY_LOGI("Unsubscribe datashare ready success");
276 }
277 if (statusChangeListener_ != nullptr) {
278 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
279 if (samgrProxy != nullptr) {
280 samgrProxy->UnSubscribeSystemAbility(OHOS::COMMON_EVENT_SERVICE_ID, statusChangeListener_);
281 statusChangeListener_ = nullptr;
282 TELEPHONY_LOGI("Unsubscribe COMMON_EVENT_SERVICE_ID success");
283 }
284 }
285 }
286
InitListener()287 void MultiSimMonitor::InitListener()
288 {
289 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
290 statusChangeListener_ = new (std::nothrow) SystemAbilityStatusChangeListener(*this);
291 if (samgrProxy == nullptr || statusChangeListener_ == nullptr) {
292 TELEPHONY_LOGE("samgrProxy or statusChangeListener_ is nullptr");
293 return;
294 }
295 auto ret = samgrProxy->SubscribeSystemAbility(COMMON_EVENT_SERVICE_ID, statusChangeListener_);
296 TELEPHONY_LOGI("SubscribeSystemAbility COMMON_EVENT_SERVICE_ID result is %{public}d", ret);
297 CheckOpcNeedUpdata(false);
298 }
299
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)300 void MultiSimMonitor::SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId,
301 const std::string &deviceId)
302 {
303 switch (systemAbilityId) {
304 case COMMON_EVENT_SERVICE_ID: {
305 TELEPHONY_LOGI("COMMON_EVENT_SERVICE_ID is running");
306 handler_.SubscribeDataShareReady();
307 break;
308 }
309 default:
310 TELEPHONY_LOGE("systemAbilityId is invalid");
311 break;
312 }
313 }
314
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)315 void MultiSimMonitor::SystemAbilityStatusChangeListener::OnRemoveSystemAbility(int32_t systemAbilityId,
316 const std::string &deviceId)
317 {
318 switch (systemAbilityId) {
319 case COMMON_EVENT_SERVICE_ID: {
320 TELEPHONY_LOGI("COMMON_EVENT_SERVICE_ID stopped");
321 break;
322 }
323 default:
324 TELEPHONY_LOGE("systemAbilityId is invalid");
325 break;
326 }
327 }
328
SubscribeDataShareReady()329 void MultiSimMonitor::SubscribeDataShareReady()
330 {
331 if (dataShareSubscriber_ != nullptr) {
332 TELEPHONY_LOGW("datashare ready has Subscribed");
333 return;
334 }
335 MatchingSkills matchingSkills;
336 matchingSkills.AddEvent(DATASHARE_READY_EVENT);
337 CommonEventSubscribeInfo subscriberInfo(matchingSkills);
338 subscriberInfo.SetThreadMode(CommonEventSubscribeInfo::COMMON);
339 dataShareSubscriber_ = std::make_shared<DataShareEventSubscriber>(subscriberInfo, *this);
340 if (CommonEventManager::SubscribeCommonEvent(dataShareSubscriber_)) {
341 TELEPHONY_LOGI("Subscribe datashare ready success");
342 } else {
343 dataShareSubscriber_ = nullptr;
344 TELEPHONY_LOGE("Subscribe datashare ready fail");
345 }
346 CheckDataShareError();
347 }
348
OnReceiveEvent(const CommonEventData & data)349 void MultiSimMonitor::DataShareEventSubscriber::OnReceiveEvent(const CommonEventData &data)
350 {
351 OHOS::EventFwk::Want want = data.GetWant();
352 std::string action = want.GetAction();
353 TELEPHONY_LOGI("action = %{public}s", action.c_str());
354 if (action == DATASHARE_READY_EVENT) {
355 handler_.CheckDataShareError();
356 handler_.CheckSimNotifyRegister();
357 }
358 }
359
CheckSimNotifyRegister()360 void MultiSimMonitor::CheckSimNotifyRegister()
361 {
362 RemoveEvent(MultiSimMonitor::REGISTER_SIM_NOTIFY_RETRY_EVENT);
363 setRemainCount(INIT_TIMES);
364 RegisterSimNotify();
365 }
366
CheckDataShareError()367 void MultiSimMonitor::CheckDataShareError()
368 {
369 if (controller_->IsDataShareError()) {
370 controller_->ResetDataShareError();
371 CheckOpcNeedUpdata(true);
372 }
373 }
374
setRemainCount(int remainCount)375 void MultiSimMonitor::setRemainCount(int remainCount)
376 {
377 remainCount_ = remainCount;
378 }
379
RegisterSimAccountCallback(const int32_t tokenId,const sptr<SimAccountCallback> & callback)380 int32_t MultiSimMonitor::RegisterSimAccountCallback(
381 const int32_t tokenId, const sptr<SimAccountCallback> &callback)
382 {
383 if (callback == nullptr) {
384 TELEPHONY_LOGE(" callback is nullptr");
385 return TELEPHONY_ERR_ARGUMENT_NULL;
386 }
387 std::lock_guard<std::mutex> lock(mutexInner_);
388 bool isExisted = false;
389 for (auto &iter : listSimAccountCallbackRecord_) {
390 if (iter.tokenId == tokenId) {
391 iter.simAccountCallback = callback;
392 isExisted = true;
393 break;
394 }
395 }
396 if (isExisted) {
397 TELEPHONY_LOGI("Ignore register action, since callback is existent");
398 return TELEPHONY_SUCCESS;
399 }
400
401 SimAccountCallbackRecord simAccountRecord;
402 simAccountRecord.tokenId = tokenId;
403 simAccountRecord.simAccountCallback = callback;
404 listSimAccountCallbackRecord_.push_back(simAccountRecord);
405 TELEPHONY_LOGI("Register successfully, callback list size is %{public}zu", listSimAccountCallbackRecord_.size());
406 return TELEPHONY_SUCCESS;
407 }
408
UnregisterSimAccountCallback(const int32_t tokenId)409 int32_t MultiSimMonitor::UnregisterSimAccountCallback(const int32_t tokenId)
410 {
411 std::lock_guard<std::mutex> lock(mutexInner_);
412 bool isSuccess = false;
413 auto iter = listSimAccountCallbackRecord_.begin();
414 for (; iter != listSimAccountCallbackRecord_.end();) {
415 if (iter->tokenId == tokenId) {
416 iter = listSimAccountCallbackRecord_.erase(iter);
417 isSuccess = true;
418 break;
419 }
420 iter++;
421 }
422 if (!isSuccess) {
423 TELEPHONY_LOGE("Ignore unregister action, since callback is nonexistent");
424 return TELEPHONY_ERROR;
425 }
426 TELEPHONY_LOGI("Unregister successfully, callback list size is %{public}zu", listSimAccountCallbackRecord_.size());
427 return TELEPHONY_SUCCESS;
428 }
429
GetSimAccountCallbackRecords()430 std::list<MultiSimMonitor::SimAccountCallbackRecord> MultiSimMonitor::GetSimAccountCallbackRecords()
431 {
432 std::lock_guard<std::mutex> lock(mutexInner_);
433 return listSimAccountCallbackRecord_;
434 }
435
NotifySimAccountChanged()436 void MultiSimMonitor::NotifySimAccountChanged()
437 {
438 std::list<SimAccountCallbackRecord> CallbackRecord = GetSimAccountCallbackRecords();
439 TELEPHONY_LOGD("CallbackRecord size is %{public}zu", CallbackRecord.size());
440 for (auto iter : CallbackRecord) {
441 if (iter.simAccountCallback != nullptr) {
442 iter.simAccountCallback->OnSimAccountChanged();
443 }
444 }
445 DelayedRefSingleton<TelephonyStateRegistryClient>::GetInstance().UpdateIccAccount();
446 }
447
RegisterSimNotify()448 void MultiSimMonitor::RegisterSimNotify()
449 {
450 if (isForgetAllDataDone_) {
451 TELEPHONY_LOGI("RegisterSimNotify has done");
452 return;
453 }
454 if (controller_ == nullptr) {
455 TELEPHONY_LOGE("MultiSimController is null");
456 return;
457 }
458 if (!controller_->ForgetAllData()) {
459 if (remainCount_ > 0) {
460 SendEvent(MultiSimMonitor::REGISTER_SIM_NOTIFY_RETRY_EVENT, 0, DELAY_TIME);
461 TELEPHONY_LOGI("retry remain %{public}d", static_cast<int32_t>(remainCount_));
462 remainCount_--;
463 }
464 return;
465 }
466 isForgetAllDataDone_ = true;
467 TELEPHONY_LOGI("Register with time left %{public}d", static_cast<int32_t>(remainCount_));
468 for (size_t slotId = 0; slotId < simFileManager_.size(); slotId++) {
469 RegisterSimNotify(static_cast<int32_t>(slotId));
470 }
471 }
472
RegisterSimNotify(int32_t slotId)473 void MultiSimMonitor::RegisterSimNotify(int32_t slotId)
474 {
475 if (!IsValidSlotId(slotId)) {
476 TELEPHONY_LOGE("RegisterSimNotify slotId is invalid");
477 return;
478 }
479 auto simFileManager = simFileManager_[slotId].lock();
480 if (simFileManager == nullptr) {
481 TELEPHONY_LOGE("simFileManager is null slotId : %{public}d", slotId);
482 return;
483 }
484 simFileManager->RegisterCoreNotify(shared_from_this(), RadioEvent::RADIO_QUERY_ICCID_DONE);
485 if (simStateManager_[slotId] == nullptr) {
486 TELEPHONY_LOGE("simStateManager is null slotId : %{public}d", slotId);
487 return;
488 }
489 simStateManager_[slotId]->RegisterCoreNotify(shared_from_this(), RadioEvent::RADIO_SIM_STATE_CHANGE);
490 simStateManager_[slotId]->RegisterCoreNotify(shared_from_this(), RadioEvent::RADIO_SIM_STATE_LOCKED);
491 simStateManager_[slotId]->RegisterCoreNotify(shared_from_this(), RadioEvent::RADIO_SIM_STATE_READY);
492 TELEPHONY_LOGI("RegisterSimNotify %{public}d", slotId);
493 }
494
UnRegisterSimNotify()495 void MultiSimMonitor::UnRegisterSimNotify()
496 {
497 for (size_t slotId = 0; slotId < simFileManager_.size(); slotId++) {
498 auto simFileManager = simFileManager_[slotId].lock();
499 if (simFileManager == nullptr) {
500 TELEPHONY_LOGE("simFileManager is null slotId : %{public}zu", slotId);
501 continue;
502 }
503 simFileManager->UnRegisterCoreNotify(shared_from_this(), RadioEvent::RADIO_QUERY_ICCID_DONE);
504 if (simStateManager_[slotId] == nullptr) {
505 TELEPHONY_LOGE("simStateManager is null slotId : %{public}zu", slotId);
506 continue;
507 }
508 simStateManager_[slotId]->UnRegisterCoreNotify(shared_from_this(), RadioEvent::RADIO_SIM_STATE_CHANGE);
509 simStateManager_[slotId]->UnRegisterCoreNotify(shared_from_this(), RadioEvent::RADIO_SIM_STATE_LOCKED);
510 simStateManager_[slotId]->UnRegisterCoreNotify(shared_from_this(), RadioEvent::RADIO_SIM_STATE_READY);
511 }
512 }
513 } // namespace Telephony
514 } // namespace OHOS
515