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