• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "usim_dialling_numbers_service.h"
17 
18 namespace OHOS {
19 namespace Telephony {
20 constexpr int32_t ANR_RECORD_TYPE_ADDITIONAL_DATA = 2;
21 constexpr int32_t MIN_ANR_RECORD_LENGTH_BYTES = 15;
22 constexpr int32_t ANR_ADDITION_NUMBER_LENGTH_OFFSET = 1;
23 constexpr int32_t ANR_ADDITION_NUMBER_OFFSET = 3;
24 constexpr int32_t MAX_EXT_BCD_LENGTH = 10;
25 const std::u16string NUMBER_SPLIT = u";";
26 std::mutex UsimDiallingNumbersService::mtx_;
27 
UsimDiallingNumbersService()28 UsimDiallingNumbersService::UsimDiallingNumbersService() : TelEventHandler("UsimDiallingNumbersService")
29 {
30     InitFuncMap();
31 }
32 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)33 void UsimDiallingNumbersService::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
34 {
35     if (event == nullptr) {
36         TELEPHONY_LOGI("UsimDiallingNumbersService::ProcessEvent event is null");
37         return;
38     }
39     uint32_t id = event->GetInnerEventId();
40     auto itFunc = memberFuncMap_.find(id);
41     if (itFunc != memberFuncMap_.end()) {
42         auto memberFunc = itFunc->second;
43         if (memberFunc != nullptr) {
44             memberFunc(event);
45         }
46     }
47 }
48 
InitFuncMap()49 void UsimDiallingNumbersService::InitFuncMap()
50 {
51     memberFuncMap_[MSG_USIM_PBR_LOAD_DONE] =
52         [this](const AppExecFwk::InnerEvent::Pointer &event) { ProcessPbrLoadDone(event); };
53     memberFuncMap_[MSG_USIM_ADN_LOAD_DONE] =
54         [this](const AppExecFwk::InnerEvent::Pointer &event) { ProcessDiallingNumberLoadDone(event); };
55     memberFuncMap_[MSG_USIM_ANR_LOAD_DONE] =
56         [this](const AppExecFwk::InnerEvent::Pointer &event) { ProcessDiallingNumber2LoadDone(event); };
57 }
58 
ProcessPbrLoadDone(const AppExecFwk::InnerEvent::Pointer & event)59 void UsimDiallingNumbersService::ProcessPbrLoadDone(const AppExecFwk::InnerEvent::Pointer &event)
60 {
61     if (event == nullptr) {
62         TELEPHONY_LOGE("event is nullptr!");
63         return;
64     }
65     std::shared_ptr<MultiRecordResult> object = event->GetSharedObject<MultiRecordResult>();
66     if (object != nullptr) {
67         TELEPHONY_LOGI("UsimDiallingNumbersService::ProcessPbrLoadDone: %{public}d", object->resultLength);
68         if (object->exception == nullptr) {
69             std::vector<std::string> &files = object->fileResults;
70             GeneratePbrFile(files);
71         }
72     } else {
73         TELEPHONY_LOGE("ProcessPbrLoadDone: get null pointer!!!");
74     }
75     TELEPHONY_LOGI("ProcessPbrLoadDone start load %{public}zu", pbrFiles_.size());
76     if (pbrFiles_.empty()) {
77         std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> list =
78             std::make_shared<std::vector<std::shared_ptr<DiallingNumbersInfo>>>();
79         SendBackResult(list);
80         TELEPHONY_LOGI("ProcessPbrLoadDone empty pbr");
81     } else {
82         pbrIndex_ = 0;
83         LoadDiallingNumberFiles(pbrIndex_);
84     }
85 }
86 
ProcessDiallingNumberLoadDone(const AppExecFwk::InnerEvent::Pointer & event)87 void UsimDiallingNumbersService::ProcessDiallingNumberLoadDone(const AppExecFwk::InnerEvent::Pointer &event)
88 {
89     if (event == nullptr) {
90         return;
91     }
92 
93     if (pbrIndex_ >= pbrFiles_.size()) {
94         TELEPHONY_LOGI("loadEfFilesFromUsim: finished");
95         SendLocalBack();
96         return;
97     }
98 
99     std::unique_ptr<DiallingNumbersHandlerResult> resultObject = event->GetUniqueObject<DiallingNumbersHandlerResult>();
100     if (resultObject == nullptr) {
101         TELEPHONY_LOGE("process adn file: object is nullptr");
102         LoadDiallingNumberFiles(++pbrIndex_);
103         return;
104     }
105     if (resultObject->exception != nullptr) {
106         auto exception = std::static_pointer_cast<RadioResponseInfo>(resultObject->exception);
107         TELEPHONY_LOGE("process adn file exception occured, errno: %{public}d",
108             static_cast<uint32_t>(exception->error));
109         LoadDiallingNumberFiles(++pbrIndex_);
110         return;
111     }
112 
113     if (resultObject->result == nullptr) {
114         TELEPHONY_LOGE("process adn file result nullptr");
115         LoadDiallingNumberFiles(++pbrIndex_);
116         return;
117     }
118 
119     std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> diallingNumberList =
120         std::static_pointer_cast<std::vector<std::shared_ptr<DiallingNumbersInfo>>>(resultObject->result);
121     diallingNumbersFromAdn_ = *diallingNumberList;
122     LoadDiallingNumber2Files(pbrIndex_);
123 }
FetchAnrContent(const std::string & recordData)124 std::u16string UsimDiallingNumbersService::FetchAnrContent(const std::string &recordData)
125 {
126     int recordLen = 0;
127     std::shared_ptr<unsigned char> data = SIMUtils::HexStringConvertToBytes(recordData, recordLen);
128     if (data == nullptr) {
129         TELEPHONY_LOGE("anr file record bytes null data");
130         return u"";
131     }
132     /* parse record lenth */
133     if (recordLen < MIN_ANR_RECORD_LENGTH_BYTES) {
134         TELEPHONY_LOGE("anr file record record length error");
135         return u"";
136     }
137     unsigned char *record = data.get();
138     /* parse extension data lenth */
139     int length = static_cast<int>(record[ANR_ADDITION_NUMBER_LENGTH_OFFSET]);
140     if (length > MAX_EXT_BCD_LENGTH) {
141         length = MAX_EXT_BCD_LENGTH;
142         TELEPHONY_LOGE("FetchExtensionContent number error");
143     }
144     /* parse extension data */
145     std::string number2 =
146         SimNumberDecode::ExtensionBCDConvertToString(data, recordLen, ANR_ADDITION_NUMBER_OFFSET, length);
147     return Str8ToStr16(number2);
148 }
149 
MergeDiallingNumbers(const std::vector<std::u16string> & number2s)150 void UsimDiallingNumbersService::MergeDiallingNumbers(const std::vector<std::u16string> &number2s)
151 {
152     if (diallingNumbersFromAdn_.size() != number2s.size()) {
153         TELEPHONY_LOGE(
154             "adn size [%{public}zu] not equal anr size [%{public}zu]", diallingNumbersFromAdn_.size(), number2s.size());
155         return;
156     }
157     for (size_t i = 0; i < number2s.size(); i++) {
158         if (!number2s[i].empty()) {
159             auto numbers = diallingNumbersFromAdn_[i]->GetNumber() + NUMBER_SPLIT + number2s[i];
160             diallingNumbersFromAdn_[i]->UpdateNumber(numbers);
161         }
162     }
163 }
164 
ProcessDiallingNumber2LoadDone(const AppExecFwk::InnerEvent::Pointer & event)165 void UsimDiallingNumbersService::ProcessDiallingNumber2LoadDone(const AppExecFwk::InnerEvent::Pointer &event)
166 {
167     if (event == nullptr) {
168         TELEPHONY_LOGE("event is nullptr!");
169         return;
170     }
171     std::shared_ptr<MultiRecordResult> object = event->GetSharedObject<MultiRecordResult>();
172     if (object != nullptr) {
173         std::vector<std::string> &dataList = object->fileResults;
174         std::vector<std::u16string> number2s;
175         for (size_t i = 0; i < dataList.size(); i++) {
176             number2s.push_back(FetchAnrContent(dataList[i]));
177         }
178         MergeDiallingNumbers(number2s);
179     }
180     auto tmp = std::make_shared<std::vector<std::shared_ptr<DiallingNumbersInfo>>>();
181     tmp->swap(diallingNumbersFromAdn_);
182     FillDiallingNumbersRecords(tmp);
183 
184     TELEPHONY_LOGI("load pbr files to Tap: %{public}d %{public}zu", pbrIndex_, pbrFiles_.size());
185     LoadDiallingNumberFiles(++pbrIndex_);
186 }
187 
FillDiallingNumbersRecords(const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> & list)188 void UsimDiallingNumbersService::FillDiallingNumbersRecords(
189     const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> &list)
190 {
191     if (list != nullptr) {
192         for (std::vector<std::shared_ptr<DiallingNumbersInfo>>::iterator it = list->begin(); it != list->end(); ++it) {
193             diallingNumbersFiles_.push_back(*it);
194         }
195         TELEPHONY_LOGI(
196             "UsimDiallingNumbersService::FillDiallingNumbersRecords  %{public}zu", diallingNumbersFiles_.size());
197     } else {
198         TELEPHONY_LOGE("FillDiallingNumbersRecords: get null vectors!!!");
199     }
200 }
201 
ObtainUsimElementaryFiles(const AppExecFwk::InnerEvent::Pointer & pointer)202 void UsimDiallingNumbersService::ObtainUsimElementaryFiles(const AppExecFwk::InnerEvent::Pointer &pointer)
203 {
204     callerPointer_ = std::move(const_cast<AppExecFwk::InnerEvent::Pointer &>(pointer));
205     if (diallingNumbersFiles_.empty()) {
206         if (pbrFiles_.empty()) {
207             LoadPbrFiles();
208         }
209     }
210 }
211 
LoadPbrFiles()212 void UsimDiallingNumbersService::LoadPbrFiles()
213 {
214     std::unique_lock<std::mutex> lock(mtx_);
215     diallingNumbersFiles_.clear();
216     AppExecFwk::InnerEvent::Pointer event = BuildCallerInfo(MSG_USIM_PBR_LOAD_DONE);
217     if (fileController_ == nullptr) {
218         TELEPHONY_LOGE("LoadPbrFiles fileController_ is nullptr");
219         return;
220     }
221     fileController_->ObtainAllLinearFixedFile(ELEMENTARY_FILE_PBR, event);
222 }
223 
LoadDiallingNumberFiles(size_t recId)224 bool UsimDiallingNumbersService::LoadDiallingNumberFiles(size_t recId)
225 {
226     if (recId >= pbrFiles_.size()) {
227         TELEPHONY_LOGI("LoadDiallingNumberFiles finish %{public}zu", recId);
228         NextStep(MSG_USIM_ADN_LOAD_DONE);
229         return false;
230     }
231 
232     std::unique_lock<std::mutex> lock(mtx_);
233     std::map<int, std::shared_ptr<TagData>> files = pbrFiles_.at(recId)->fileIds_;
234     if (files.find(TAG_SIM_USIM_EXT1) == files.end() || files.find(TAG_SIM_USIM_ADN) == files.end()) {
235         TELEPHONY_LOGE("pbr tag data is incomplete at index: %{public}zu", recId);
236         NextStep(MSG_USIM_ADN_LOAD_DONE);
237         return false;
238     }
239 
240     int extEf = files.at(TAG_SIM_USIM_EXT1) != nullptr ? files.at(TAG_SIM_USIM_EXT1)->fileId : 0;
241     if (extEf >= 0 && files.at(TAG_SIM_USIM_ADN) != nullptr) {
242         TELEPHONY_LOGI("UsimDiallingNumbersService::LoadDiallingNumberFiles start %{public}zu", recId);
243         int efId = files.at(TAG_SIM_USIM_ADN)->fileId;
244         AppExecFwk::InnerEvent::Pointer event = CreateHandlerPointer(MSG_USIM_ADN_LOAD_DONE, efId, 0, nullptr);
245         if (diallingNumbersHandler_ == nullptr) {
246             TELEPHONY_LOGE("LoadDiallingNumberFiles diallingNumbersHandler_ is nullptr");
247             return false;
248         }
249         diallingNumbersHandler_->GetAllDiallingNumbers(efId, extEf, event);
250         return true;
251     } else {
252         bool fileNull = files.at(TAG_SIM_USIM_ADN) == nullptr;
253         TELEPHONY_LOGE("LoadDiallingNumberFiles error params %{public}d, nullfile %{public}d", extEf, fileNull);
254         NextStep(MSG_USIM_ADN_LOAD_DONE);
255         return false;
256     }
257 }
258 
LoadDiallingNumber2Files(size_t recId)259 bool UsimDiallingNumbersService::LoadDiallingNumber2Files(size_t recId)
260 {
261     std::unique_lock<std::mutex> lock(mtx_);
262     if (recId >= pbrFiles_.size()) {
263         TELEPHONY_LOGE("load number anr files error: recId over");
264         NextStep(MSG_USIM_ANR_LOAD_DONE);
265         return false;
266     }
267     std::map<int, std::shared_ptr<TagData>> files = pbrFiles_.at(recId)->fileIds_;
268     auto anrIter = files.find(TAG_SIM_USIM_ANR);
269     if (anrIter == files.end()) {
270         TELEPHONY_LOGE("load number anr files error: have not anr file");
271         NextStep(MSG_USIM_ANR_LOAD_DONE);
272         return false;
273     }
274     std::shared_ptr<TagData> anrTag = anrIter->second;
275     if (anrTag == nullptr) {
276         TELEPHONY_LOGE("load number anr files error: anr file is nullptr");
277         NextStep(MSG_USIM_ANR_LOAD_DONE);
278         return false;
279     }
280     AppExecFwk::InnerEvent::Pointer event = BuildCallerInfo(MSG_USIM_ANR_LOAD_DONE);
281     if (fileController_ == nullptr) {
282         TELEPHONY_LOGE("LoadPbrFiles fileController_ is nullptr");
283         return false;
284     }
285     fileController_->ObtainAllLinearFixedFile(anrTag->fileId, event);
286     return true;
287 }
288 
GeneratePbrFile(std::vector<std::string> & records)289 void UsimDiallingNumbersService::GeneratePbrFile(std::vector<std::string> &records)
290 {
291     pbrFileLoaded_ = !records.empty() && pbrFileLoaded_;
292     pbrFiles_.clear();
293     constexpr size_t FstByteChrLen = 2;
294     for (const auto &dataPac : records) {
295         TELEPHONY_LOGI("GeneratePbrFile: %{public}s", dataPac.c_str());
296         if (dataPac.size() < FstByteChrLen) {
297             continue;
298         }
299         auto subStr = dataPac.substr(0, FstByteChrLen);
300         if (subStr == "FF" || subStr == "ff") {
301             continue;
302         }
303         auto pbrFile = BuildNumberFileByRecord(dataPac);
304         if (pbrFile != nullptr) {
305             pbrFiles_.push_back(pbrFile);
306             auto fileIt = pbrFile->fileIds_.find(TAG_SIM_USIM_ADN);
307             if (fileIt == pbrFile->fileIds_.end()) {
308                 continue;
309             }
310             std::shared_ptr<TagData> file = fileIt->second;
311             if (file == nullptr || file->shortFileId == INVALID_SFI) {
312                 continue;
313             }
314             efIdOfSfi_.insert(std::pair<int, int>(file->shortFileId, file->fileId));
315         }
316     }
317 }
318 
BuildCallerInfo(int eventId)319 AppExecFwk::InnerEvent::Pointer UsimDiallingNumbersService::BuildCallerInfo(int eventId)
320 {
321     std::unique_ptr<FileToControllerMsg> object = std::make_unique<FileToControllerMsg>();
322     int eventParam = 0;
323     AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(eventId, object, eventParam);
324     if (event == nullptr) {
325         TELEPHONY_LOGE("event is nullptr!");
326         return AppExecFwk::InnerEvent::Pointer(nullptr, nullptr);
327     }
328     event->SetOwner(shared_from_this());
329     return event;
330 }
331 
CreateHandlerPointer(int eventid,int efId,int index,std::shared_ptr<void> pobj)332 AppExecFwk::InnerEvent::Pointer UsimDiallingNumbersService::CreateHandlerPointer(
333     int eventid, int efId, int index, std::shared_ptr<void> pobj)
334 {
335     std::unique_ptr<DiallingNumbersHandleHolder> holder = std::make_unique<DiallingNumbersHandleHolder>();
336     holder->fileID = efId;
337     holder->index = index;
338     holder->diallingNumber = pobj;
339     int eventParam = 0;
340     AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(eventid, holder, eventParam);
341     if (event == nullptr) {
342         TELEPHONY_LOGE("event is nullptr!");
343         return AppExecFwk::InnerEvent::Pointer(nullptr, nullptr);
344     }
345     event->SetOwner(shared_from_this());
346     return event;
347 }
348 
SetFileControllerAndDiallingNumberHandler(std::shared_ptr<IccFileController> & ctrl,std::shared_ptr<IccDiallingNumbersHandler> handler)349 void UsimDiallingNumbersService::SetFileControllerAndDiallingNumberHandler(
350     std::shared_ptr<IccFileController> &ctrl, std::shared_ptr<IccDiallingNumbersHandler> handler)
351 {
352     fileController_ = ctrl;
353     diallingNumbersHandler_ = handler;
354 }
355 
BuildNumberFileByRecord(const std::string & record)356 std::shared_ptr<UsimDiallingNumberFile> UsimDiallingNumbersService::BuildNumberFileByRecord(
357     const std::string &record)
358 {
359     std::shared_ptr<TagService> recTlv = std::make_shared<TagService>(record);
360     std::shared_ptr<UsimDiallingNumberFile> file = std::make_shared<UsimDiallingNumberFile>();
361     int tag = 0;
362     TELEPHONY_LOGI("BuildNumberFileByRecord: start get tag");
363     while (recTlv->Next()) {
364         tag = recTlv->GetTagCode();
365         TELEPHONY_LOGI("front tag type: %{public}d", tag);
366         if ((tag != TYPE1_FLAG) && (tag != TYPE2_FLAG) && (tag != TYPE3_FLAG)) {
367             TELEPHONY_LOGE("the tag:'%{public}d' need in {%{public}d,%{public}d,%{public}d}", tag, TYPE1_FLAG,
368                 TYPE2_FLAG, TYPE3_FLAG);
369             continue;
370         }
371         std::vector<uint8_t> datav;
372         recTlv->GetValue(datav);
373         auto tlvEfSfi = std::make_shared<TagService>(datav);
374         StorePbrDetailInfo(file, tlvEfSfi, tag);
375     }
376     return file;
377 }
378 
StorePbrDetailInfo(std::shared_ptr<UsimDiallingNumberFile> file,std::shared_ptr<TagService> tlv,int parentTag)379 void UsimDiallingNumbersService::StorePbrDetailInfo(
380     std::shared_ptr<UsimDiallingNumberFile> file, std::shared_ptr<TagService> tlv, int parentTag)
381 {
382     if (tlv == nullptr) {
383         TELEPHONY_LOGI("StorePbrDetailInfo: tlv is nullptr!");
384         return;
385     }
386     for (int count = 0; tlv->Next(); ++count) {
387         const int tag = tlv->GetTagCode();
388         TELEPHONY_LOGI("make file tag type: %{public}d", tag);
389         if ((tag < TAG_SIM_USIM_ADN) || (tag > TAG_SIM_USIM_CCP1)) {
390             TELEPHONY_LOGE("the tag:'%{public}d' need in range [%{public}d,%{public}d]", tag, TAG_SIM_USIM_ADN,
391                 TAG_SIM_USIM_CCP1);
392             continue;
393         }
394         // 3GPP TS 31.102, 4.4.2.1 EF_PBR
395         std::vector<uint8_t> data;
396         tlv->GetValue(data);
397         auto dataIt = data.begin();
398         if (dataIt == data.end()) {
399             TELEPHONY_LOGE("the length of data == 0 ?!");
400             continue;
401         }
402         uint32_t efid = *dataIt;
403         ++dataIt;
404         if (dataIt == data.end()) {
405             TELEPHONY_LOGE("the length of data only one ?!");
406             continue;
407         }
408         efid <<= BIT_OF_BYTE;
409         efid |= *dataIt;
410         ++dataIt;
411         int sfi = (dataIt == data.end()) ? 0 : static_cast<int>((*dataIt));
412         std::shared_ptr<TagData> deltaFile = std::make_shared<TagData>(parentTag, efid, sfi, count);
413         TELEPHONY_LOGI(
414             "MakeFiles result[ parentTag:%{public}d, efid:%{public}d, sfi:%{public}d, count:%{public}d ]",
415             parentTag, efid, sfi, count);
416         file->fileIds_.insert(std::pair<int, std::shared_ptr<TagData>>(tag, deltaFile));
417     }
418 }
419 
SendBackResult(const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> & diallingnumbers)420 void UsimDiallingNumbersService::SendBackResult(
421     const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> &diallingnumbers)
422 {
423     if (callerPointer_ == nullptr) {
424         TELEPHONY_LOGE("callerPointer_ is nullptr");
425         return;
426     }
427     auto owner = callerPointer_->GetOwner();
428     if (owner == nullptr) {
429         TELEPHONY_LOGE("owner is nullptr");
430         return;
431     }
432     uint32_t id = callerPointer_->GetInnerEventId();
433     std::unique_ptr<UsimFetcher> fd = callerPointer_->GetUniqueObject<UsimFetcher>();
434     std::unique_ptr<UsimResult> data = std::make_unique<UsimResult>(fd.get());
435     if (data == nullptr) {
436         TELEPHONY_LOGE("data is nullptr");
437         return;
438     }
439     data->result = static_cast<std::shared_ptr<void>>(diallingnumbers);
440     TelEventHandler::SendTelEvent(owner, id, data);
441     TELEPHONY_LOGI("UsimDiallingNumbersService::SendBackResult send end");
442 }
443 
SendLocalBack()444 void UsimDiallingNumbersService::UsimDiallingNumbersService::SendLocalBack()
445 {
446     auto diallingnumbers = std::make_shared<std::vector<std::shared_ptr<DiallingNumbersInfo>>>(diallingNumbersFiles_);
447     SendBackResult(diallingnumbers);
448 }
449 
NextStep(int msgId)450 void UsimDiallingNumbersService::NextStep(int msgId)
451 {
452     std::unique_ptr<int> step = std::make_unique<int>(NEXT);
453     SendEvent(msgId, step);
454 }
455 
~UsimDiallingNumbersService()456 UsimDiallingNumbersService::~UsimDiallingNumbersService() {}
457 } // namespace Telephony
458 } // namespace OHOS
459