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