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 std::mutex UsimDiallingNumbersService::mtx_;
21 
UsimDiallingNumbersService()22 UsimDiallingNumbersService::UsimDiallingNumbersService() : TelEventHandler("UsimDiallingNumbersService")
23 {
24     InitFuncMap();
25 }
26 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)27 void UsimDiallingNumbersService::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
28 {
29     if (event == nullptr) {
30         TELEPHONY_LOGI("UsimDiallingNumbersService::ProcessEvent event is null");
31         return;
32     }
33     uint32_t id = event->GetInnerEventId();
34     TELEPHONY_LOGD("UsimDiallingNumbersService::ProcessEvent Id is %{public}d", id);
35     std::unique_ptr<ControllerToFileMsg> fd = event->GetUniqueObject<ControllerToFileMsg>();
36     if (fd != nullptr) {
37         if (fd->exception != nullptr) {
38             TELEPHONY_LOGE("UsimDiallingNumbersService::ProcessEvent: get error result");
39             SendLocalBack();
40             return;
41         }
42     }
43     auto itFunc = memberFuncMap_.find(id);
44     if (itFunc != memberFuncMap_.end()) {
45         auto memberFunc = itFunc->second;
46         if (memberFunc != nullptr) {
47             memberFunc(event);
48         }
49     }
50 }
51 
InitFuncMap()52 void UsimDiallingNumbersService::InitFuncMap()
53 {
54     memberFuncMap_[MSG_USIM_PBR_LOAD_DONE] =
55         [this](const AppExecFwk::InnerEvent::Pointer &event) { ProcessPbrLoadDone(event); };
56     memberFuncMap_[MSG_USIM_USIM_ADN_LOAD_DONE] =
57         [this](const AppExecFwk::InnerEvent::Pointer &event) { ProcessDiallingNumberLoadDone(event); };
58 }
59 
ProcessPbrLoadDone(const AppExecFwk::InnerEvent::Pointer & event)60 void UsimDiallingNumbersService::ProcessPbrLoadDone(const AppExecFwk::InnerEvent::Pointer &event)
61 {
62     if (event == nullptr) {
63         TELEPHONY_LOGE("event is nullptr!");
64         return;
65     }
66     std::shared_ptr<MultiRecordResult> object = event->GetSharedObject<MultiRecordResult>();
67     if (object != nullptr) {
68         TELEPHONY_LOGI("UsimDiallingNumbersService::ProcessPbrLoadDone: %{public}d", object->resultLength);
69         if (object->exception == nullptr) {
70             std::vector<std::string> &files = object->fileResults;
71             GeneratePbrFile(files);
72         }
73     } else {
74         TELEPHONY_LOGE("ProcessPbrLoadDone: get null pointer!!!");
75     }
76     TELEPHONY_LOGI("ProcessPbrLoadDone start load %{public}zu", pbrFiles_.size());
77     if (pbrFiles_.empty()) {
78         std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> list =
79             std::make_shared<std::vector<std::shared_ptr<DiallingNumbersInfo>>>();
80         SendBackResult(list);
81         TELEPHONY_LOGI("ProcessPbrLoadDone empty pbr");
82     } else {
83         pbrIndex_ = 0;
84         LoadDiallingNumberFiles(pbrIndex_);
85     }
86 }
87 
ProcessDiallingNumberLoadDone(const AppExecFwk::InnerEvent::Pointer & event)88 void UsimDiallingNumbersService::ProcessDiallingNumberLoadDone(const AppExecFwk::InnerEvent::Pointer &event)
89 {
90     if (event == nullptr) {
91         return;
92     }
93     std::unique_ptr<DiallingNumbersHandlerResult> object = event->GetUniqueObject<DiallingNumbersHandlerResult>();
94 
95     if (object != nullptr) {
96         if (object->exception == nullptr) {
97             std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> diallingNumberList =
98                 std::static_pointer_cast<std::vector<std::shared_ptr<DiallingNumbersInfo>>>(object->result);
99             FillDiallingNumbersRecords(diallingNumberList);
100         } else {
101             TELEPHONY_LOGE("ProcessDiallingNumberLoadDone: exception occured");
102         }
103     }
104 
105     if (pbrIndex_ < pbrFiles_.size()) {
106         TELEPHONY_LOGI(
107             "ProcessDiallingNumberLoadDone to Tap: %{public}d %{public}zu", pbrIndex_, pbrFiles_.size());
108         LoadDiallingNumberFiles(++pbrIndex_);
109     } else {
110         TELEPHONY_LOGI("loadEfFilesFromUsim: finished");
111         SendLocalBack();
112     }
113 }
114 
FillDiallingNumbersRecords(const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> & list)115 void UsimDiallingNumbersService::FillDiallingNumbersRecords(
116     const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> &list)
117 {
118     if (list != nullptr) {
119         for (std::vector<std::shared_ptr<DiallingNumbersInfo>>::iterator it = list->begin(); it != list->end(); ++it) {
120             diallingNumbersFiles_.push_back(*it);
121         }
122         TELEPHONY_LOGI(
123             "UsimDiallingNumbersService::FillDiallingNumbersRecords  %{public}zu", diallingNumbersFiles_.size());
124     } else {
125         TELEPHONY_LOGE("FillDiallingNumbersRecords: get null vectors!!!");
126     }
127 }
128 
ObtainUsimElementaryFiles(const AppExecFwk::InnerEvent::Pointer & pointer)129 void UsimDiallingNumbersService::ObtainUsimElementaryFiles(const AppExecFwk::InnerEvent::Pointer &pointer)
130 {
131     callerPointer_ = std::move(const_cast<AppExecFwk::InnerEvent::Pointer &>(pointer));
132     if (diallingNumbersFiles_.empty()) {
133         if (pbrFiles_.empty()) {
134             LoadPbrFiles();
135         }
136     }
137 }
138 
LoadPbrFiles()139 void UsimDiallingNumbersService::LoadPbrFiles()
140 {
141     std::unique_lock<std::mutex> lock(mtx_);
142     AppExecFwk::InnerEvent::Pointer event = BuildCallerInfo(MSG_USIM_PBR_LOAD_DONE);
143     if (fileController_ == nullptr) {
144         TELEPHONY_LOGE("LoadPbrFiles fileController_ is nullptr");
145         return;
146     }
147     fileController_->ObtainAllLinearFixedFile(ELEMENTARY_FILE_PBR, event);
148 }
149 
LoadDiallingNumberFiles(int recId)150 bool UsimDiallingNumbersService::LoadDiallingNumberFiles(int recId)
151 {
152     if (recId >= static_cast<int>(pbrFiles_.size())) {
153         TELEPHONY_LOGI("LoadDiallingNumberFiles finish %{public}d", recId);
154         NextStep(MSG_USIM_USIM_ADN_LOAD_DONE);
155         return false;
156     }
157 
158     std::unique_lock<std::mutex> lock(mtx_);
159     std::map<int, std::shared_ptr<TagData>> files = pbrFiles_.at(recId)->fileIds_;
160     if (files.empty() || !files.size()) {
161         TELEPHONY_LOGI("LoadDiallingNumberFiles empty file %{public}d", recId);
162         NextStep(MSG_USIM_USIM_ADN_LOAD_DONE);
163         return false;
164     }
165 
166     int extEf = files.at(TAG_SIM_USIM_EXT1) != nullptr ? files.at(TAG_SIM_USIM_EXT1)->fileId : 0;
167     if (extEf >= 0 && files.at(TAG_SIM_USIM_ADN) != nullptr) {
168         TELEPHONY_LOGI("UsimDiallingNumbersService::LoadDiallingNumberFiles start %{public}d", recId);
169         int efId = files.at(TAG_SIM_USIM_ADN)->fileId;
170         AppExecFwk::InnerEvent::Pointer event = CreateHandlerPointer(MSG_USIM_USIM_ADN_LOAD_DONE, efId, 0, nullptr);
171         if (diallingNumbersHandler_ == nullptr) {
172             TELEPHONY_LOGE("LoadDiallingNumberFiles diallingNumbersHandler_ is nullptr");
173             return false;
174         }
175         diallingNumbersHandler_->GetAllDiallingNumbers(efId, extEf, event);
176         return true;
177     } else {
178         bool fileNull = files.at(TAG_SIM_USIM_ADN) == nullptr;
179         TELEPHONY_LOGE("LoadDiallingNumberFiles error params %{public}d, nullfile %{public}d", extEf, fileNull);
180         NextStep(MSG_USIM_USIM_ADN_LOAD_DONE);
181         return false;
182     }
183 }
184 
GeneratePbrFile(std::vector<std::string> & records)185 void UsimDiallingNumbersService::GeneratePbrFile(std::vector<std::string> &records)
186 {
187     pbrFileLoaded_ = !records.empty() && pbrFileLoaded_;
188     pbrFiles_.clear();
189     constexpr size_t FstByteChrLen = 2;
190     for (const auto &dataPac : records) {
191         TELEPHONY_LOGI("GeneratePbrFile: %{public}s", dataPac.c_str());
192         if (dataPac.size() < FstByteChrLen) {
193             continue;
194         }
195         auto subStr = dataPac.substr(0, FstByteChrLen);
196         if (subStr == "FF" || subStr == "ff") {
197             continue;
198         }
199         auto pbrFile = BuildNumberFileByRecord(dataPac);
200         if (pbrFile != nullptr) {
201             pbrFiles_.push_back(pbrFile);
202             auto fileIt = pbrFile->fileIds_.find(TAG_SIM_USIM_ADN);
203             if (fileIt == pbrFile->fileIds_.end()) {
204                 continue;
205             }
206             std::shared_ptr<TagData> file = fileIt->second;
207             if (file == nullptr || file->shortFileId == INVALID_SFI) {
208                 continue;
209             }
210             efIdOfSfi_.insert(std::pair<int, int>(file->shortFileId, file->fileId));
211         }
212     }
213 }
214 
BuildCallerInfo(int eventId)215 AppExecFwk::InnerEvent::Pointer UsimDiallingNumbersService::BuildCallerInfo(int eventId)
216 {
217     std::unique_ptr<FileToControllerMsg> object = std::make_unique<FileToControllerMsg>();
218     int eventParam = 0;
219     AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(eventId, object, eventParam);
220     if (event == nullptr) {
221         TELEPHONY_LOGE("event is nullptr!");
222         return AppExecFwk::InnerEvent::Pointer(nullptr, nullptr);
223     }
224     event->SetOwner(shared_from_this());
225     return event;
226 }
227 
CreateHandlerPointer(int eventid,int efId,int index,std::shared_ptr<void> pobj)228 AppExecFwk::InnerEvent::Pointer UsimDiallingNumbersService::CreateHandlerPointer(
229     int eventid, int efId, int index, std::shared_ptr<void> pobj)
230 {
231     std::unique_ptr<DiallingNumbersHandleHolder> holder = std::make_unique<DiallingNumbersHandleHolder>();
232     if (holder == nullptr) {
233         TELEPHONY_LOGE("holder is nullptr!");
234         return AppExecFwk::InnerEvent::Pointer(nullptr, nullptr);
235     }
236     holder->fileID = efId;
237     holder->index = index;
238     holder->diallingNumber = pobj;
239     int eventParam = 0;
240     AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(eventid, holder, eventParam);
241     if (event == nullptr) {
242         TELEPHONY_LOGE("event is nullptr!");
243         return AppExecFwk::InnerEvent::Pointer(nullptr, nullptr);
244     }
245     event->SetOwner(shared_from_this());
246     return event;
247 }
248 
SetFileControllerAndDiallingNumberHandler(std::shared_ptr<IccFileController> & ctrl,std::shared_ptr<IccDiallingNumbersHandler> handler)249 void UsimDiallingNumbersService::SetFileControllerAndDiallingNumberHandler(
250     std::shared_ptr<IccFileController> &ctrl, std::shared_ptr<IccDiallingNumbersHandler> handler)
251 {
252     fileController_ = ctrl;
253     diallingNumbersHandler_ = handler;
254 }
255 
BuildNumberFileByRecord(const std::string & record)256 std::shared_ptr<UsimDiallingNumberFile> UsimDiallingNumbersService::BuildNumberFileByRecord(
257     const std::string &record)
258 {
259     std::shared_ptr<TagService> recTlv = std::make_shared<TagService>(record);
260     if (recTlv == nullptr) {
261         TELEPHONY_LOGI("BuildNumberFileByRecord: recTlv is nullptr!");
262         return nullptr;
263     }
264     std::shared_ptr<UsimDiallingNumberFile> file = std::make_shared<UsimDiallingNumberFile>();
265     int tag = 0;
266     TELEPHONY_LOGI("BuildNumberFileByRecord: start get tag");
267     while (recTlv->Next()) {
268         tag = recTlv->GetTagCode();
269         TELEPHONY_LOGI("front tag type: %{public}d", tag);
270         if ((tag != TYPE1_FLAG) && (tag != TYPE2_FLAG) && (tag != TYPE3_FLAG)) {
271             TELEPHONY_LOGE("the tag:'%{public}d' need in {%{public}d,%{public}d,%{public}d}", tag, TYPE1_FLAG,
272                 TYPE2_FLAG, TYPE3_FLAG);
273             continue;
274         }
275         std::vector<uint8_t> datav;
276         recTlv->GetValue(datav);
277         auto tlvEfSfi = std::make_shared<TagService>(datav);
278         StorePbrDetailInfo(file, tlvEfSfi, tag);
279     }
280     return file;
281 }
282 
StorePbrDetailInfo(std::shared_ptr<UsimDiallingNumberFile> file,std::shared_ptr<TagService> tlv,int parentTag)283 void UsimDiallingNumbersService::StorePbrDetailInfo(
284     std::shared_ptr<UsimDiallingNumberFile> file, std::shared_ptr<TagService> tlv, int parentTag)
285 {
286     if (tlv == nullptr) {
287         TELEPHONY_LOGI("StorePbrDetailInfo: tlv is nullptr!");
288         return;
289     }
290     for (int count = 0; tlv->Next(); ++count) {
291         const int tag = tlv->GetTagCode();
292         TELEPHONY_LOGI("make file tag type: %{public}d", tag);
293         if ((tag < TAG_SIM_USIM_ADN) || (tag > TAG_SIM_USIM_CCP1)) {
294             TELEPHONY_LOGE("the tag:'%{public}d' need in range [%{public}d,%{public}d]", tag, TAG_SIM_USIM_ADN,
295                 TAG_SIM_USIM_CCP1);
296             continue;
297         }
298         // 3GPP TS 31.102, 4.4.2.1 EF_PBR
299         std::vector<uint8_t> data;
300         tlv->GetValue(data);
301         auto dataIt = data.begin();
302         if (dataIt == data.end()) {
303             TELEPHONY_LOGE("the length of data == 0 ?!");
304             continue;
305         }
306         uint32_t efid = *dataIt;
307         ++dataIt;
308         if (dataIt == data.end()) {
309             TELEPHONY_LOGE("the length of data only one ?!");
310             continue;
311         }
312         efid <<= BIT_OF_BYTE;
313         efid |= *dataIt;
314         ++dataIt;
315         int sfi = (dataIt == data.end()) ? 0 : static_cast<int>((*dataIt));
316         std::shared_ptr<TagData> deltaFile = std::make_shared<TagData>(parentTag, efid, sfi, count);
317         TELEPHONY_LOGI(
318             "MakeFiles result[ parentTag:%{public}d, efid:%{public}d, sfi:%{public}d, count:%{public}d ]",
319             parentTag, efid, sfi, count);
320         file->fileIds_.insert(std::pair<int, std::shared_ptr<TagData>>(tag, deltaFile));
321     }
322 }
323 
SendBackResult(const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> & diallingnumbers)324 void UsimDiallingNumbersService::SendBackResult(
325     const std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> &diallingnumbers)
326 {
327     if (callerPointer_ == nullptr) {
328         TELEPHONY_LOGE("callerPointer_ is nullptr");
329         return;
330     }
331     auto owner = callerPointer_->GetOwner();
332     if (owner == nullptr) {
333         TELEPHONY_LOGE("owner is nullptr");
334         return;
335     }
336     uint32_t id = callerPointer_->GetInnerEventId();
337     std::unique_ptr<UsimFetcher> fd = callerPointer_->GetUniqueObject<UsimFetcher>();
338     std::unique_ptr<UsimResult> data = std::make_unique<UsimResult>(fd.get());
339     if (data == nullptr) {
340         TELEPHONY_LOGE("data is nullptr");
341         return;
342     }
343     data->result = static_cast<std::shared_ptr<void>>(diallingnumbers);
344     TelEventHandler::SendTelEvent(owner, id, data);
345     TELEPHONY_LOGI("UsimDiallingNumbersService::SendBackResult send end");
346 }
347 
SendLocalBack()348 void UsimDiallingNumbersService::UsimDiallingNumbersService::SendLocalBack()
349 {
350     std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>> diallingnumbers =
351         std::shared_ptr<std::vector<std::shared_ptr<DiallingNumbersInfo>>>(&diallingNumbersFiles_);
352     SendBackResult(diallingnumbers);
353 }
354 
NextStep(int msgId)355 void UsimDiallingNumbersService::NextStep(int msgId)
356 {
357     std::unique_ptr<int> step = std::make_unique<int>(NEXT);
358     SendEvent(msgId, step);
359 }
360 
~UsimDiallingNumbersService()361 UsimDiallingNumbersService::~UsimDiallingNumbersService() {}
362 } // namespace Telephony
363 } // namespace OHOS
364