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