1 /*
2 * Copyright (C) 2021 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 "icc_dialling_numbers_cache.h"
17 #include "usim_dialling_numbers_service.h"
18 #include "icc_dialling_numbers_handler.h"
19
20 namespace OHOS {
21 namespace Telephony {
IccDiallingNumbersCache(std::shared_ptr<SimFileManager> simFileManager)22 IccDiallingNumbersCache::IccDiallingNumbersCache(std::shared_ptr<SimFileManager> simFileManager)
23 : TelEventHandler("IccDiallingNumbersCache"), simFileManager_(simFileManager)
24 {
25 InitFileTypeMap();
26 }
27
~IccDiallingNumbersCache()28 IccDiallingNumbersCache::~IccDiallingNumbersCache() {}
29
Init()30 void IccDiallingNumbersCache::Init()
31 {
32 if ((usimDiallingNumberSrv_ != nullptr) && (diallingNumbersHandler_ != nullptr)) {
33 TELEPHONY_LOGI("IccDiallingNumbersCache init already done");
34 return;
35 }
36 if (simFileManager_ == nullptr) {
37 TELEPHONY_LOGE("IccDiallingNumbersCache int get null pointer");
38 return;
39 }
40 diallingNumbersHandler_ = simFileManager_->ObtainDiallingNumberHandler();
41 if (diallingNumbersHandler_ == nullptr) {
42 TELEPHONY_LOGE("IccDiallingNumbersCache failed to InitDiallingNumbersLoader");
43 return;
44 }
45
46 usimDiallingNumberSrv_ = std::make_shared<UsimDiallingNumbersService>();
47 if (usimDiallingNumberSrv_ == nullptr) {
48 TELEPHONY_LOGE("IccDiallingNumbersCache failed to create usimpdiallingnumbers.");
49 return;
50 }
51 std::shared_ptr<IccFileController> fileController = simFileManager_->GetIccFileController();
52 usimDiallingNumberSrv_->SetFileControllerAndDiallingNumberHandler(fileController, diallingNumbersHandler_);
53 }
54
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)55 void IccDiallingNumbersCache::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
56 {
57 if (event == nullptr) {
58 TELEPHONY_LOGE("event is nullptr!");
59 return;
60 }
61 uint32_t id = event->GetInnerEventId();
62 switch (id) {
63 case MSG_SIM_OBTAIN_ADN_DETAILS_DONE:
64 ProcessObtainAdnDetailsDone(event);
65 break;
66 case MSG_SIM_CHANGE_DIALLING_NUMBERS_DONE:
67 ProcessChangeDiallingNumbersDone(event);
68 break;
69 case MSG_SIM_OBTAIN_PBR_DETAILS_DONE:
70 ProcessObtainPbrDetailsDone(event);
71 break;
72 default:
73 break;
74 }
75 }
76
ClearDiallingNumberCache()77 void IccDiallingNumbersCache::ClearDiallingNumberCache()
78 {
79 diallingNumberFileList_.clear();
80 }
81
ProcessObtainPbrDetailsDone(const AppExecFwk::InnerEvent::Pointer & event)82 void IccDiallingNumbersCache::ProcessObtainPbrDetailsDone(const AppExecFwk::InnerEvent::Pointer &event)
83 {
84 std::unique_ptr<UsimResult> fd = event->GetUniqueObject<UsimResult>();
85 if (fd == nullptr) {
86 TELEPHONY_LOGE("fd is nullptr!");
87 return;
88 }
89 int fileId = fd->fileID;
90 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> diallingNumberList =
91 std::static_pointer_cast<std::vector<std::shared_ptr<DiallingNumbersInfo>>>(fd->result);
92 auto iter = diallingNumberFileList_.find(fileId);
93 if (iter != diallingNumberFileList_.end()) {
94 diallingNumberFileList_.erase(fileId);
95 }
96 diallingNumberFileList_.insert(
97 std::pair<int, std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>>>(
98 fileId, diallingNumberList));
99 SendBackResult(fd->callerCache->caller, diallingNumberList, fd->exception);
100 TELEPHONY_LOGI("IccDiallingNumbersCache::ProcessUsimDiallingNumberLoadDone finished");
101 }
102
ProcessObtainAdnDetailsDone(const AppExecFwk::InnerEvent::Pointer & event)103 void IccDiallingNumbersCache::ProcessObtainAdnDetailsDone(const AppExecFwk::InnerEvent::Pointer &event)
104 {
105 std::unique_ptr<DiallingNumbersHandlerResult> fd = event->GetUniqueObject<DiallingNumbersHandlerResult>();
106 if (fd == nullptr) {
107 TELEPHONY_LOGE("fd is nullptr!");
108 return;
109 }
110 int fileId = fd->fileID;
111 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> diallingNumberList =
112 std::static_pointer_cast<std::vector<std::shared_ptr<DiallingNumbersInfo>>>(fd->result);
113 if (diallingNumberList == nullptr) {
114 TELEPHONY_LOGE("diallingNumber loader ProcessObtainAdnDetailsDone error occured");
115 } else {
116 TELEPHONY_LOGI("ProcessObtainAdnDetailsDone %{public}zu", diallingNumberList->size());
117 }
118 auto iter = diallingNumberFileList_.find(fileId);
119 if (iter != diallingNumberFileList_.end()) {
120 diallingNumberFileList_.erase(fileId);
121 }
122 diallingNumberFileList_.insert(
123 std::pair<int, std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>>>(
124 fileId, diallingNumberList));
125 SendBackResult(fd->callerCache->caller, diallingNumberList, fd->exception);
126 TELEPHONY_LOGI("IccDiallingNumbersCache::ProcessObtainAdnDetailsDone finished");
127 }
128
ProcessChangeDiallingNumbersDone(const AppExecFwk::InnerEvent::Pointer & event)129 void IccDiallingNumbersCache::ProcessChangeDiallingNumbersDone(const AppExecFwk::InnerEvent::Pointer &event)
130 {
131 std::unique_ptr<DiallingNumbersHandlerResult> fd = event->GetUniqueObject<DiallingNumbersHandlerResult>();
132 if (fd == nullptr) {
133 TELEPHONY_LOGE("fd is nullptr!");
134 return;
135 }
136 int fileId = fd->fileID;
137 int index = fd->index;
138 std::shared_ptr<DiallingNumbersInfo> diallingNumber = std::static_pointer_cast<DiallingNumbersInfo>(fd->result);
139 auto iter = diallingNumberFileList_.find(fileId);
140 if (iter != diallingNumberFileList_.end()) {
141 if (fd->exception == nullptr) {
142 diallingNumberFileList_.at(fileId)->at(index - 1) = diallingNumber;
143 } else {
144 std::shared_ptr<RadioResponseInfo> responseInfo =
145 std::static_pointer_cast<RadioResponseInfo>(fd->exception);
146 if (responseInfo == nullptr) {
147 TELEPHONY_LOGE("responseInfo is nullptr");
148 return;
149 }
150 if (responseInfo->error == ErrType::NONE) {
151 diallingNumberFileList_.at(fileId)->at(index - 1) = diallingNumber;
152 }
153 }
154 } else {
155 TELEPHONY_LOGE("no diallingNumber list");
156 }
157 SendUpdateResult(fd->callerCache->caller, fd->exception);
158 TELEPHONY_LOGI("IccDiallingNumbersCache::ProcessChangeDiallingNumbersDone finished");
159 }
160
LoadReadyDiallingNumbers(int fileId)161 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> IccDiallingNumbersCache::LoadReadyDiallingNumbers
162 (int fileId)
163 {
164 auto itDiallingNumbers = diallingNumberFileList_.find(fileId);
165 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> diallingNumberList = nullptr;
166 if (itDiallingNumbers != diallingNumberFileList_.end()) {
167 diallingNumberList = itDiallingNumbers->second;
168 }
169 return diallingNumberList;
170 }
171
ExtendedElementFile(int fileId)172 int IccDiallingNumbersCache::ExtendedElementFile(int fileId)
173 {
174 auto iter = extTypeMap_.find(fileId);
175 return (iter != extTypeMap_.end()) ? iter->second : -1;
176 }
177
UpdateDiallingNumberToIcc(int fileId,std::shared_ptr<DiallingNumbersInfo> diallingNumberInfor,int index,bool isDel,const AppExecFwk::InnerEvent::Pointer & caller)178 void IccDiallingNumbersCache::UpdateDiallingNumberToIcc(int fileId,
179 std::shared_ptr<DiallingNumbersInfo> diallingNumberInfor, int index,
180 bool isDel, const AppExecFwk::InnerEvent::Pointer &caller)
181 {
182 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> oldDiallingNumberList =
183 LoadReadyDiallingNumbers(fileId);
184
185 if (oldDiallingNumberList == nullptr) {
186 SendExceptionResult(caller, LOADER_ERROR);
187 TELEPHONY_LOGE("WriteDiallingNumberToSim not load at first");
188 return;
189 }
190 if (diallingNumberInfor == nullptr) {
191 TELEPHONY_LOGE("diallingNumberInfor is nullptr!");
192 return;
193 }
194 if (isDel && index == DiallingNumbersInfo::EMPTY_INDEX) {
195 SearchIndexByNameAndNumber(oldDiallingNumberList, diallingNumberInfor, index);
196 }
197 if (!CheckValueAndOperation(oldDiallingNumberList, diallingNumberInfor, index, fileId)) {
198 SendExceptionResult(caller, LOADER_ERROR);
199 return;
200 }
201 diallingNumberInfor->elementaryFileId_ = fileId;
202 diallingNumberInfor->index_ = index;
203 std::string pin2 = Str16ToStr8(diallingNumberInfor->pin2_);
204 diallingNumberInfor->pin2_ = u""; // reset
205
206 DiallingNumberUpdateInfor infor;
207 infor.diallingNumber = diallingNumberInfor;
208 infor.fileId = fileId;
209 infor.extFile = ExtendedElementFile(fileId);
210 infor.index = index;
211 infor.pin2 = (fileId == ELEMENTARY_FILE_ADN) ? "" : pin2;
212 infor.isDel = isDel;
213 AppExecFwk::InnerEvent::Pointer event =
214 BuildCallerInfo(MSG_SIM_CHANGE_DIALLING_NUMBERS_DONE, fileId, index, diallingNumberInfor, caller);
215 if (diallingNumbersHandler_ != nullptr) {
216 diallingNumbersHandler_->UpdateDiallingNumbers(infor, event);
217 }
218 }
219
CheckValueAndOperation(const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> & list,const std::shared_ptr<DiallingNumbersInfo> & info,int & index,int fileId)220 bool IccDiallingNumbersCache::CheckValueAndOperation(
221 const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> &list,
222 const std::shared_ptr<DiallingNumbersInfo> &info, int &index, int fileId)
223 {
224 if (index == ADD_FLAG) { // insert into nullpos
225 int count = 0;
226 for (auto it = list->begin(); it != list->end(); it++) {
227 std::shared_ptr<DiallingNumbersInfo> &item = *it;
228 count++;
229 if (item->IsEmpty()) { // find first null position for save
230 index = count;
231 return true;
232 }
233 }
234 } else {
235 auto iter = diallingNumberFileList_.find(fileId);
236 if (iter != diallingNumberFileList_.end()) {
237 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> &vc = iter->second;
238 int size = static_cast<int>(vc->size());
239 if ((index < 1) || (index > size)) { // check index range
240 TELEPHONY_LOGE("error index!!");
241 return false;
242 }
243 }
244 // check unnormal opearion del or update
245 for (auto it = list->begin(); it != list->end(); it++) {
246 std::shared_ptr<DiallingNumbersInfo> &item = *it;
247 if (item->GetIndex() == index && item->IsEmpty()) {
248 TELEPHONY_LOGE("update or del on null pos, invalid operation!!");
249 return false;
250 }
251 }
252 }
253 return true;
254 }
255
SearchIndexByNameAndNumber(const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> & list,const std::shared_ptr<DiallingNumbersInfo> & info,int & index)256 void IccDiallingNumbersCache::SearchIndexByNameAndNumber(
257 const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> &list,
258 const std::shared_ptr<DiallingNumbersInfo> &info, int &index)
259 {
260 for (auto it = list->begin(); it != list->end(); it++) {
261 std::shared_ptr<DiallingNumbersInfo> &item = *it;
262 if (item == nullptr) {
263 continue;
264 }
265 if (IsDiallingNumberEqual(info, item)) {
266 index = item->GetIndex();
267 TELEPHONY_LOGI("Search index is %{public}d", index);
268 }
269 }
270 }
271
ObtainAllDiallingNumberFiles(int fileId,int extFileId,const AppExecFwk::InnerEvent::Pointer & caller)272 void IccDiallingNumbersCache::ObtainAllDiallingNumberFiles(
273 int fileId, int extFileId, const AppExecFwk::InnerEvent::Pointer &caller)
274 {
275 TELEPHONY_LOGI("ObtainAllDiallingNumberFiles fileId: %{public}d %{public}d", fileId, extFileId);
276 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> result = LoadReadyDiallingNumbers(fileId);
277
278 if (result != nullptr && caller != nullptr) {
279 std::shared_ptr<void> object = nullptr;
280 TELEPHONY_LOGI("ObtainAllDiallingNumberFiles has already loaded");
281 SendBackResult(caller, result, object);
282 return;
283 }
284
285 if (fileId == ELEMENTARY_FILE_PBR) {
286 TELEPHONY_LOGI("ObtainAllDiallingNumberFiles start usim adn");
287 AppExecFwk::InnerEvent::Pointer pointer = CreateUsimPointer(MSG_SIM_OBTAIN_PBR_DETAILS_DONE, fileId, caller);
288 if (usimDiallingNumberSrv_ != nullptr) {
289 usimDiallingNumberSrv_->ObtainUsimElementaryFiles(pointer);
290 }
291 } else {
292 AppExecFwk::InnerEvent::Pointer event = BuildCallerInfo(
293 MSG_SIM_OBTAIN_ADN_DETAILS_DONE, fileId, 0, nullptr, caller);
294 if (diallingNumbersHandler_ != nullptr) {
295 diallingNumbersHandler_->GetAllDiallingNumbers(fileId, extFileId, event);
296 }
297 }
298 }
299
SendExceptionResult(const AppExecFwk::InnerEvent::Pointer & caller,int errCode)300 void IccDiallingNumbersCache::SendExceptionResult(const AppExecFwk::InnerEvent::Pointer &caller, int errCode)
301 {
302 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> diallingNumberList = nullptr;
303 std::shared_ptr<RadioResponseInfo> responseInfo = std::make_shared<RadioResponseInfo>();
304 responseInfo->error = static_cast<Telephony::ErrType>(errCode);
305 std::shared_ptr<void> exception = static_cast<std::shared_ptr<void>>(responseInfo);
306 SendBackResult(caller, diallingNumberList, exception);
307 }
308
SendBackResult(const AppExecFwk::InnerEvent::Pointer & callPointer,const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> & ar,const std::shared_ptr<void> & object)309 void IccDiallingNumbersCache::SendBackResult(const AppExecFwk::InnerEvent::Pointer &callPointer,
310 const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> &ar,
311 const std::shared_ptr<void> &object)
312 {
313 if (callPointer == nullptr) {
314 TELEPHONY_LOGE("callPointer is null pointer");
315 return;
316 }
317 auto owner = callPointer->GetOwner();
318 uint32_t id = callPointer->GetInnerEventId();
319 std::unique_ptr<ResultObtain> fd = callPointer->GetUniqueObject<ResultObtain>();
320 if (fd == nullptr) {
321 TELEPHONY_LOGE("fd is nullptr!");
322 return;
323 }
324 std::unique_ptr<ResponseResult> data = std::make_unique<ResponseResult>(fd.get());
325 if (data == nullptr) {
326 TELEPHONY_LOGE("data is nullptr!");
327 return;
328 }
329 data->result = static_cast<std::shared_ptr<void>>(ar);
330 data->exception = object;
331 if (owner != nullptr) {
332 TelEventHandler::SendTelEvent(owner, id, data);
333 } else {
334 TELEPHONY_LOGE("IccDiallingNumbersCache::SendBackResult null owner");
335 }
336 }
337
SendUpdateResult(const AppExecFwk::InnerEvent::Pointer & response,const std::shared_ptr<void> & object)338 void IccDiallingNumbersCache::SendUpdateResult(
339 const AppExecFwk::InnerEvent::Pointer &response, const std::shared_ptr<void> &object)
340 {
341 std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> diallingNumbers = nullptr;
342 SendBackResult(response, diallingNumbers, object);
343 }
344
BuildCallerInfo(int eventid,int efId,int index,std::shared_ptr<void> pobj,const AppExecFwk::InnerEvent::Pointer & caller)345 AppExecFwk::InnerEvent::Pointer IccDiallingNumbersCache::BuildCallerInfo(
346 int eventid, int efId, int index, std::shared_ptr<void> pobj, const AppExecFwk::InnerEvent::Pointer &caller)
347 {
348 std::unique_ptr<DiallingNumbersHandleHolder> holder = std::make_unique<DiallingNumbersHandleHolder>();
349 holder->fileID = efId;
350 holder->index = index;
351 holder->diallingNumber = pobj;
352 holder->callerCache = std::make_shared<PointerWrapper>();
353 holder->callerCache->caller = std::move(const_cast<AppExecFwk::InnerEvent::Pointer &>(caller));
354 int eventParam = 0;
355 AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(eventid, holder, eventParam);
356 if (event == nullptr) {
357 TELEPHONY_LOGE("event is nullptr!");
358 return AppExecFwk::InnerEvent::Pointer(nullptr, nullptr);
359 }
360 event->SetOwner(shared_from_this());
361 return event;
362 }
363
CreateUsimPointer(int eventid,int efId,const AppExecFwk::InnerEvent::Pointer & caller)364 AppExecFwk::InnerEvent::Pointer IccDiallingNumbersCache::CreateUsimPointer(
365 int eventid, int efId, const AppExecFwk::InnerEvent::Pointer &caller)
366 {
367 std::unique_ptr<UsimFetcher> holder = std::make_unique<UsimFetcher>();
368 holder->fileID = efId;
369 holder->callerCache = std::make_shared<PointerWrapper>();
370 holder->callerCache->caller = std::move(const_cast<AppExecFwk::InnerEvent::Pointer &>(caller));
371 int eventParam = 0;
372 AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(eventid, holder, eventParam);
373 if (event == nullptr) {
374 TELEPHONY_LOGE("event is nullptr!");
375 return AppExecFwk::InnerEvent::Pointer(nullptr, nullptr);
376 }
377 event->SetOwner(shared_from_this());
378 return event;
379 }
380
IsDiallingNumberEqual(const std::shared_ptr<DiallingNumbersInfo> & src,const std::shared_ptr<DiallingNumbersInfo> & dest)381 bool IccDiallingNumbersCache::IsDiallingNumberEqual(
382 const std::shared_ptr<DiallingNumbersInfo> &src, const std::shared_ptr<DiallingNumbersInfo> &dest)
383 {
384 if (src == nullptr) {
385 TELEPHONY_LOGE("src is nullptr!");
386 return false;
387 }
388 return (StringEqual(src->name_, dest->name_) &&
389 StringEqual(src->number_, dest->number_) && ArrayEqual(src->emails_, dest->emails_));
390 }
391
StringEqual(const std::u16string & s1,const std::u16string & s2)392 bool IccDiallingNumbersCache::StringEqual(const std::u16string &s1, const std::u16string &s2)
393 {
394 return s1.compare(s2) == 0;
395 }
396
ArrayEqual(const std::vector<std::u16string> & mailsSrc,const std::vector<std::u16string> & mailsDest)397 bool IccDiallingNumbersCache::ArrayEqual(
398 const std::vector<std::u16string> &mailsSrc, const std::vector<std::u16string> &mailsDest)
399 {
400 return std::equal(mailsSrc.begin(), mailsSrc.end(), mailsDest.begin(), mailsDest.end());
401 }
402
InitFileTypeMap()403 void IccDiallingNumbersCache::InitFileTypeMap()
404 {
405 extTypeMap_[ELEMENTARY_FILE_MBDN] = ELEMENTARY_FILE_EXT6;
406 extTypeMap_[ELEMENTARY_FILE_ADN] = ELEMENTARY_FILE_EXT1;
407 extTypeMap_[ELEMENTARY_FILE_SDN] = ELEMENTARY_FILE_EXT3;
408 extTypeMap_[ELEMENTARY_FILE_FDN] = ELEMENTARY_FILE_EXT2;
409 extTypeMap_[ELEMENTARY_FILE_MSISDN] = ELEMENTARY_FILE_EXT1;
410 extTypeMap_[ELEMENTARY_FILE_PBR] = 0;
411 }
412 } // namespace Telephony
413 } // namespace OHOS
414