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