1 /*
2 * Copyright (C) 2021-2024 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 "ruim_file.h"
17
18 #include "common_event_manager.h"
19 #include "common_event_support.h"
20 #include "radio_event.h"
21 #include "telephony_common_utils.h"
22 #include "telephony_ext_wrapper.h"
23 #include "configuration.h"
24 #include "app_mgr_client.h"
25
26 using namespace std;
27 using namespace OHOS::AppExecFwk;
28 using namespace OHOS::EventFwk;
29
30 namespace OHOS {
31 namespace Telephony {
RuimFile(std::shared_ptr<SimStateManager> simStateManager)32 RuimFile::RuimFile(std::shared_ptr<SimStateManager> simStateManager) : IccFile("RuimFile", simStateManager)
33 {
34 fileQueried_ = false;
35 InitMemberFunc();
36 }
37
StartLoad()38 void RuimFile::StartLoad()
39 {
40 TELEPHONY_LOGI("RuimFile::StartLoad() start");
41 LoadRuimFiles();
42 }
43
ObtainSimOperator()44 std::string RuimFile::ObtainSimOperator()
45 {
46 if (operatorNumeric_.empty()) {
47 std::string imsi = ObtainIMSI();
48 if (imsi.empty()) {
49 TELEPHONY_LOGE("RuimFile::ObtainSimOperator: IMSI is null");
50 return "";
51 }
52 if ((lengthOfMnc_ != UNINITIALIZED_MNC) && (lengthOfMnc_ != UNKNOWN_MNC)) {
53 operatorNumeric_ = imsi.substr(0, MCC_LEN + lengthOfMnc_);
54 }
55 std::string mcc = imsi.substr(0, MCC_LEN);
56 if (operatorNumeric_.empty() && IsValidDecValue(mcc)) {
57 operatorNumeric_ = imsi.substr(0, MCC_LEN + MccPool::ShortestMncLengthFromMcc(std::stoi(mcc)));
58 }
59 }
60 return operatorNumeric_;
61 }
62
ObtainIsoCountryCode()63 std::string RuimFile::ObtainIsoCountryCode()
64 {
65 std::string numeric = ObtainSimOperator();
66 if (numeric.empty()) {
67 TELEPHONY_LOGE("RuimFile ObtainIsoCountryCode: numeric is null");
68 return "";
69 }
70 size_t len = numeric.length();
71 std::string mcc = numeric.substr(0, MCC_LEN);
72 if (len >= MCC_LEN && IsValidDecValue(mcc)) {
73 std::string iso = MccPool::MccCountryCode(std::stoi(mcc));
74 return iso;
75 } else {
76 return "";
77 }
78 }
79
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)80 void RuimFile::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
81 {
82 if (event == nullptr) {
83 TELEPHONY_LOGE("event is nullptr!");
84 return;
85 }
86 auto id = event->GetInnerEventId();
87 TELEPHONY_LOGD("RuimFile::ProcessEvent id %{public}d", id);
88 auto itFunc = memberFuncMap_.find(id);
89 if (itFunc != memberFuncMap_.end()) {
90 auto memberFunc = itFunc->second;
91 if (memberFunc != nullptr) {
92 bool isFileHandleResponse = memberFunc(event);
93 ProcessFileLoaded(isFileHandleResponse);
94 }
95 } else {
96 IccFile::ProcessEvent(event);
97 }
98 }
99
ProcessIccRefresh(int msgId)100 void RuimFile::ProcessIccRefresh(int msgId)
101 {
102 LoadRuimFiles();
103 }
104
ProcessFileLoaded(bool response)105 void RuimFile::ProcessFileLoaded(bool response)
106 {
107 if (!response) {
108 return;
109 }
110 fileToGet_ -= LOAD_STEP;
111 TELEPHONY_LOGI("RuimFile::ProcessFileLoaded: %{public}d requested: %{public}d", fileToGet_, fileQueried_);
112 if (ObtainFilesFetched()) {
113 OnAllFilesFetched();
114 } else if (LockQueriedOrNot()) {
115 ProcessLockedAllFilesFetched();
116 } else if (fileToGet_ < 0) {
117 fileToGet_ = 0;
118 }
119 }
120
ProcessLockedAllFilesFetched()121 void RuimFile::ProcessLockedAllFilesFetched()
122 {
123 }
124
OnAllFilesFetched()125 void RuimFile::OnAllFilesFetched()
126 {
127 UpdateLoaded(true);
128 filesFetchedObser_->NotifyObserver(RadioEvent::RADIO_SIM_RECORDS_LOADED, slotId_);
129 PublishSimFileEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SIM_STATE_CHANGED, ICC_STATE_LOADED, "");
130 LoadVoiceMail();
131 }
132
ProcessIccReady(const AppExecFwk::InnerEvent::Pointer & event)133 bool RuimFile::ProcessIccReady(const AppExecFwk::InnerEvent::Pointer &event)
134 {
135 TELEPHONY_LOGI("RuimFile::SIM_STATE_READY --received");
136 if (stateManager_->GetCardType() != CardType::SINGLE_MODE_RUIM_CARD) {
137 TELEPHONY_LOGI("invalid RuimFile::SIM_STATE_READY received");
138 return false;
139 }
140 LoadRuimFiles();
141 return false;
142 }
143
ProcessIccLocked(const AppExecFwk::InnerEvent::Pointer & event)144 bool RuimFile::ProcessIccLocked(const AppExecFwk::InnerEvent::Pointer &event)
145 {
146 TELEPHONY_LOGI(
147 "only fetch ELEMENTARY_FILE_LI, ELEMENTARY_FILE_PL and ELEMENTARY_FILE_ICCID in locked state");
148 IccFile::ProcessIccLocked();
149 lockQueried_ = true;
150 AppExecFwk::InnerEvent::Pointer eventICCID = BuildCallerInfo(MSG_SIM_OBTAIN_ICCID_DONE);
151 if (fileController_ == nullptr) {
152 TELEPHONY_LOGE("fileController_ is nullptr!");
153 return false;
154 }
155 fileController_->ObtainBinaryFile(ELEMENTARY_FILE_ICCID, eventICCID);
156 fileToGet_++;
157 return false;
158 }
159
LoadRuimFiles()160 void RuimFile::LoadRuimFiles()
161 {
162 TELEPHONY_LOGI("LoadRuimFiles started");
163 fileQueried_ = true;
164
165 AppExecFwk::InnerEvent::Pointer eventIMSI = BuildCallerInfo(MSG_SIM_OBTAIN_IMSI_DONE);
166 telRilManager_->GetImsi(slotId_, eventIMSI);
167 fileToGet_++;
168
169 AppExecFwk::InnerEvent::Pointer eventICCID = BuildCallerInfo(MSG_SIM_OBTAIN_ICCID_DONE);
170 fileController_->ObtainBinaryFile(ELEMENTARY_FILE_ICCID, eventICCID);
171 fileToGet_++;
172
173 AppExecFwk::InnerEvent::Pointer eventSpn = BuildCallerInfo(MSG_SIM_OBTAIN_CSIM_SPN_DONE);
174 fileController_->ObtainBinaryFile(ELEMENTARY_FILE_CSIM_SPN, eventSpn);
175 fileToGet_++;
176 }
177
ProcessGetSubscriptionDone(const AppExecFwk::InnerEvent::Pointer & event)178 bool RuimFile::ProcessGetSubscriptionDone(const AppExecFwk::InnerEvent::Pointer &event)
179 {
180 bool isFileHandleResponse = true;
181 return isFileHandleResponse;
182 }
183
ProcessGetIccidDone(const AppExecFwk::InnerEvent::Pointer & event)184 bool RuimFile::ProcessGetIccidDone(const AppExecFwk::InnerEvent::Pointer &event)
185 {
186 bool isFileProcessResponse = true;
187 if (event == nullptr) {
188 TELEPHONY_LOGE("event is nullptr!");
189 return isFileProcessResponse;
190 }
191 std::unique_ptr<ControllerToFileMsg> fd = event->GetUniqueObject<ControllerToFileMsg>();
192 if (fd == nullptr) {
193 TELEPHONY_LOGE("fd is nullptr!");
194 return isFileProcessResponse;
195 }
196 if (fd->exception == nullptr) {
197 std::string iccData = fd->resultData;
198 std::string fullIccData = iccData;
199 GetFullIccid(fullIccData);
200 SwapPairsForIccId(iccData);
201 TELEPHONY_LOGI("RuimFile::ProcessEvent MSG_SIM_OBTAIN_ICCID_DONE result success");
202 decIccId_ = iccData;
203 iccId_ = fullIccData;
204 FileChangeToExt(iccId_, FileChangeType::ICCID_FILE_LOAD);
205 if (filesFetchedObser_ != nullptr) {
206 TELEPHONY_LOGI("slotId:%{public}d iccid loaded", slotId_);
207 iccidLoadObser_->NotifyObserver(RadioEvent::RADIO_QUERY_ICCID_DONE, slotId_);
208 }
209 }
210 return isFileProcessResponse;
211 }
212
ProcessGetImsiDone(const AppExecFwk::InnerEvent::Pointer & event)213 bool RuimFile::ProcessGetImsiDone(const AppExecFwk::InnerEvent::Pointer &event)
214 {
215 bool isFileHandleResponse = true;
216 if (event == nullptr) {
217 TELEPHONY_LOGE("event is nullptr!");
218 return isFileHandleResponse;
219 }
220 std::shared_ptr<std::string> sharedObject = event->GetSharedObject<std::string>();
221 if (sharedObject == nullptr) {
222 TELEPHONY_LOGE("sharedObject is nullptr!");
223 return isFileHandleResponse;
224 }
225 if (sharedObject != nullptr) {
226 imsi_ = *sharedObject;
227 TELEPHONY_LOGI("RuimFile::ProcessEvent MSG_SIM_OBTAIN_IMSI_DONE");
228 SaveCountryCode();
229 if (!imsi_.empty()) {
230 imsiReadyObser_->NotifyObserver(RadioEvent::RADIO_IMSI_LOADED_READY);
231 size_t imsiSize = imsi_.size();
232 std::string mcc = "";
233 bool isSizeEnough = imsiSize >= MCC_LEN;
234 if (isSizeEnough) {
235 mcc = imsi_.substr(0, MCC_LEN);
236 }
237 std::string mnc = "";
238 isSizeEnough = imsiSize >= MCC_LEN + lengthOfMnc_;
239 if ((lengthOfMnc_ != UNINITIALIZED_MNC) && (lengthOfMnc_ != UNKNOWN_MNC) && isSizeEnough) {
240 mnc = imsi_.substr(MCC_LEN, lengthOfMnc_);
241 }
242 if (!IsValidDecValue(mcc)) {
243 TELEPHONY_LOGE("mcc is invalid decimal value");
244 return false;
245 }
246 int mncLength = MccPool::ShortestMncLengthFromMcc(std::stoi(mcc));
247 isSizeEnough = imsiSize >= MCC_LEN + mncLength;
248 if (mnc.empty() && IsValidDecValue(mcc) && isSizeEnough) {
249 mnc = imsi_.substr(MCC_LEN, mncLength);
250 }
251 AppExecFwk::Configuration configuration;
252 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_MCC, mcc);
253 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_MNC, mnc);
254 auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
255 appMgrClient->UpdateConfiguration(configuration);
256 }
257 FileChangeToExt(imsi_, FileChangeType::C_IMSI_FILE_LOAD);
258 }
259 return isFileHandleResponse;
260 }
261
ObtainMdnNumber()262 std::string RuimFile::ObtainMdnNumber()
263 {
264 return phoneNumber_;
265 }
266
ObtainCdmaMin()267 std::string RuimFile::ObtainCdmaMin()
268 {
269 return min2And1_;
270 }
271
ObtainPrlVersion()272 std::string RuimFile::ObtainPrlVersion()
273 {
274 return prlVersion_;
275 }
276
ObtainNAI()277 std::string RuimFile::ObtainNAI()
278 {
279 return nai_;
280 }
ObtainMdn()281 std::string RuimFile::ObtainMdn()
282 {
283 return mdn_;
284 }
285
ObtainMin()286 std::string RuimFile::ObtainMin()
287 {
288 return min_;
289 }
290
ObtainSid()291 std::string RuimFile::ObtainSid()
292 {
293 return systemId_;
294 }
295
ObtainNid()296 std::string RuimFile::ObtainNid()
297 {
298 return networkId_;
299 }
300
ObtainCsimSpnDisplayCondition()301 bool RuimFile::ObtainCsimSpnDisplayCondition()
302 {
303 return displayConditionOfCsimSpn_;
304 }
305
InitMemberFunc()306 void RuimFile::InitMemberFunc()
307 {
308 memberFuncMap_[RadioEvent::RADIO_SIM_STATE_READY] =
309 [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessIccReady(event); };
310 memberFuncMap_[RadioEvent::RADIO_SIM_STATE_LOCKED] =
311 [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessIccLocked(event); };
312 memberFuncMap_[RadioEvent::RADIO_SIM_STATE_SIMLOCK] =
313 [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessIccLocked(event); };
314 memberFuncMap_[MSG_SIM_OBTAIN_IMSI_DONE] =
315 [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessGetImsiDone(event); };
316 memberFuncMap_[MSG_SIM_OBTAIN_ICCID_DONE] =
317 [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessGetIccidDone(event); };
318 memberFuncMap_[MSG_SIM_OBTAIN_CDMA_SUBSCRIPTION_DONE] =
319 [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessGetSubscriptionDone(event); };
320 memberFuncMap_[MSG_SIM_OBTAIN_CSIM_SPN_DONE] =
321 [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessGetSpnDone(event); };
322 }
323
ProcessGetSpnDone(const AppExecFwk::InnerEvent::Pointer & event)324 bool RuimFile::ProcessGetSpnDone(const AppExecFwk::InnerEvent::Pointer &event)
325 {
326 bool isFileProcessResponse = true;
327 if (event == nullptr) {
328 TELEPHONY_LOGE("event is nullptr!");
329 return isFileProcessResponse;
330 }
331 std::unique_ptr<ControllerToFileMsg> fd = event->GetUniqueObject<ControllerToFileMsg>();
332 if (fd == nullptr) {
333 TELEPHONY_LOGE("fd is nullptr!");
334 return isFileProcessResponse;
335 }
336 if (fd->exception != nullptr) {
337 TELEPHONY_LOGE("EfCsimSpnFileWanted ProcessParseFile get exception");
338 return isFileProcessResponse;
339 }
340 std::string iccData = fd->resultData;
341 if (iccData.empty()) {
342 TELEPHONY_LOGE("EfCsimSpnFileWanted ProcessParseFile get empty data");
343 return isFileProcessResponse;
344 }
345 int dataLen = 0;
346 std::shared_ptr<unsigned char> fileData = SIMUtils::HexStringConvertToBytes(iccData, dataLen);
347 unsigned char* data = fileData.get();
348 displayConditionOfCsimSpn_ = ((static_cast<unsigned int>(SPN_FLAG) & static_cast<unsigned int>(data[0])) != 0);
349
350 int encoding = static_cast<int>(data[ENCODING_POS]);
351 int language = static_cast<int>(data[LANG_POS]);
352 unsigned char spnData[BUFFER_SIZE] = {0};
353
354 int len = ((dataLen - FLAG_NUM) < MAX_DATA_BYTE) ? (dataLen - FLAG_NUM) : MAX_DATA_BYTE;
355 SIMUtils::ArrayCopy(data, FLAG_NUM, spnData, 0, len);
356
357 int numBytes = 0;
358 int spnDataLen = strlen((char *)spnData);
359 for (numBytes = 0; numBytes < spnDataLen; numBytes++) {
360 if ((spnData[numBytes] & BYTE_NUM) == BYTE_NUM) {
361 break;
362 }
363 }
364
365 if (numBytes == 0) {
366 UpdateSPN("");
367 return isFileProcessResponse;
368 }
369 TELEPHONY_LOGI("EfCsimSpnFileWanted encoding is %{public}d, languange is %{public}d", encoding, language);
370 ParseSpnName(encoding, spnData, numBytes);
371 return isFileProcessResponse;
372 }
ParseSpnName(int encodeType,const unsigned char * spnData,int dataLen)373 void RuimFile::ParseSpnName(int encodeType, const unsigned char* spnData, int dataLen)
374 {
375 switch (encodeType) {
376 case CSIM_SPN_OCTET:
377 case CSIM_SPN_LATIN: {
378 std::string spnName((char*)spnData, 0, dataLen);
379 UpdateSPN(spnName);
380 }
381 break;
382 case CSIM_SPN_IA5:
383 case CSIM_SPN_7BIT_ALPHABET: {
384 std::string spnName((char*)spnData, 0, dataLen);
385 UpdateSPN(spnName);
386 }
387 break;
388 case CSIM_SPN_7BIT_ASCII: {
389 std::string spnName((char*)spnData, 0, dataLen);
390 if (SIMUtils::IsShowableAsciiOnly(spnName)) {
391 UpdateSPN(spnName);
392 } else {
393 TELEPHONY_LOGI("EfCsimSpnFileWanted Some corruption in SPN decoding = %{public}s", spnName.data());
394 }
395 }
396 break;
397 case CSIM_SPN_UNICODE_16: {
398 int outlen = 0;
399 std::shared_ptr<char16_t> cs = SIMUtils::CharsConvertToChar16(spnData, dataLen, outlen, true);
400 std::u16string hs(cs.get(), 0, outlen);
401 std::string spnName = Str16ToStr8(hs);
402 TELEPHONY_LOGI("ENCODING_UNICODE_16 spn name = %{public}s", spnName.c_str());
403 UpdateSPN(spnName);
404 }
405 break;
406 default:
407 TELEPHONY_LOGI("SPN encoding not supported");
408 }
409 }
410
ObtainSpnCondition(bool roaming,const std::string & operatorNum)411 int RuimFile::ObtainSpnCondition(bool roaming, const std::string &operatorNum)
412 {
413 return 0;
414 }
415
UpdateVoiceMail(const std::string & mailName,const std::string & mailNumber)416 bool RuimFile::UpdateVoiceMail(const std::string &mailName, const std::string &mailNumber)
417 {
418 // cdma not support
419 return false;
420 }
421
SetVoiceMailCount(int32_t voiceMailCount)422 bool RuimFile::SetVoiceMailCount(int32_t voiceMailCount)
423 {
424 // cdma not support
425 return false;
426 }
427
SetVoiceCallForwarding(bool enable,const std::string & number)428 bool RuimFile::SetVoiceCallForwarding(bool enable, const std::string &number)
429 {
430 // cdma not support
431 return false;
432 }
433
GetVoiceMailNumber()434 std::string RuimFile::GetVoiceMailNumber()
435 {
436 std::shared_lock<std::shared_mutex> lock(voiceMailMutex_);
437 return voiceMailNum_;
438 }
439
SetVoiceMailNumber(const std::string mailNumber)440 void RuimFile::SetVoiceMailNumber(const std::string mailNumber)
441 {
442 std::unique_lock<std::shared_mutex> lock(voiceMailMutex_);
443 voiceMailNum_ = mailNumber;
444 }
445
~RuimFile()446 RuimFile::~RuimFile() {}
447 } // namespace Telephony
448 } // namespace OHOS
449