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     TELEPHONY_LOGI("RuimFile::OnAllFilesFetched: start notify slotId = %{public}d", slotId_);
129     if (filesFetchedObser_ != nullptr) {
130         filesFetchedObser_->NotifyObserver(RadioEvent::RADIO_SIM_RECORDS_LOADED, slotId_);
131     }
132     if (stateManager_ != nullptr) {
133         CardType cardType = stateManager_->GetCardType();
134         NotifyRegistrySimState(cardType, SimState::SIM_STATE_LOADED, LockReason::SIM_NONE);
135     }
136     PublishSimFileEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SIM_STATE_CHANGED, ICC_STATE_LOADED, "");
137     LoadVoiceMail();
138 }
139 
ProcessIccReady(const AppExecFwk::InnerEvent::Pointer &event)140 bool RuimFile::ProcessIccReady(const AppExecFwk::InnerEvent::Pointer &event)
141 {
142     TELEPHONY_LOGI("RuimFile::SIM_STATE_READY --received");
143     if (stateManager_->GetCardType() != CardType::SINGLE_MODE_RUIM_CARD) {
144         TELEPHONY_LOGI("invalid RuimFile::SIM_STATE_READY received");
145         return false;
146     }
147     LoadRuimFiles();
148     return false;
149 }
150 
ProcessIccLocked(const AppExecFwk::InnerEvent::Pointer &event)151 bool RuimFile::ProcessIccLocked(const AppExecFwk::InnerEvent::Pointer &event)
152 {
153     TELEPHONY_LOGI(
154         "only fetch ELEMENTARY_FILE_LI, ELEMENTARY_FILE_PL and ELEMENTARY_FILE_ICCID in locked state");
155     IccFile::ProcessIccLocked();
156     lockQueried_ = true;
157     AppExecFwk::InnerEvent::Pointer eventICCID = BuildCallerInfo(MSG_SIM_OBTAIN_ICCID_DONE);
158     if (fileController_ == nullptr) {
159         TELEPHONY_LOGE("fileController_ is nullptr!");
160         return false;
161     }
162     fileController_->ObtainBinaryFile(ELEMENTARY_FILE_ICCID, eventICCID);
163     fileToGet_++;
164     return false;
165 }
166 
LoadRuimFiles()167 void RuimFile::LoadRuimFiles()
168 {
169     TELEPHONY_LOGI("LoadRuimFiles started");
170     fileQueried_ = true;
171 
172     AppExecFwk::InnerEvent::Pointer eventIMSI = BuildCallerInfo(MSG_SIM_OBTAIN_IMSI_DONE);
173     telRilManager_->GetImsi(slotId_, eventIMSI);
174     fileToGet_++;
175 
176     AppExecFwk::InnerEvent::Pointer eventICCID = BuildCallerInfo(MSG_SIM_OBTAIN_ICCID_DONE);
177     fileController_->ObtainBinaryFile(ELEMENTARY_FILE_ICCID, eventICCID);
178     fileToGet_++;
179 
180     AppExecFwk::InnerEvent::Pointer eventSpn = BuildCallerInfo(MSG_SIM_OBTAIN_CSIM_SPN_DONE);
181     fileController_->ObtainBinaryFile(ELEMENTARY_FILE_CSIM_SPN, eventSpn);
182     fileToGet_++;
183 }
184 
ProcessGetSubscriptionDone(const AppExecFwk::InnerEvent::Pointer &event)185 bool RuimFile::ProcessGetSubscriptionDone(const AppExecFwk::InnerEvent::Pointer &event)
186 {
187     bool isFileHandleResponse = true;
188     return isFileHandleResponse;
189 }
190 
ProcessGetIccidDone(const AppExecFwk::InnerEvent::Pointer &event)191 bool RuimFile::ProcessGetIccidDone(const AppExecFwk::InnerEvent::Pointer &event)
192 {
193     bool isFileProcessResponse = true;
194     if (event == nullptr) {
195         TELEPHONY_LOGE("event is nullptr!");
196         return isFileProcessResponse;
197     }
198     std::unique_ptr<ControllerToFileMsg> fd = event->GetUniqueObject<ControllerToFileMsg>();
199     if (fd == nullptr) {
200         TELEPHONY_LOGE("fd is nullptr!");
201         return isFileProcessResponse;
202     }
203     if (fd->exception == nullptr) {
204         std::string iccData = fd->resultData;
205         std::string fullIccData = iccData;
206         GetFullIccid(fullIccData);
207         SwapPairsForIccId(iccData);
208         TELEPHONY_LOGI("RuimFile::ProcessEvent MSG_SIM_OBTAIN_ICCID_DONE result success");
209         decIccId_ = iccData;
210         iccId_ = fullIccData;
211         FileChangeToExt(iccId_, FileChangeType::ICCID_FILE_LOAD);
212         if (filesFetchedObser_ != nullptr) {
213             TELEPHONY_LOGI("slotId:%{public}d iccid loaded", slotId_);
214             iccidLoadObser_->NotifyObserver(RadioEvent::RADIO_QUERY_ICCID_DONE, slotId_);
215         }
216     }
217     return isFileProcessResponse;
218 }
219 
ProcessGetImsiDone(const AppExecFwk::InnerEvent::Pointer &event)220 bool RuimFile::ProcessGetImsiDone(const AppExecFwk::InnerEvent::Pointer &event)
221 {
222     bool isFileHandleResponse = true;
223     if (event == nullptr) {
224         TELEPHONY_LOGE("event is nullptr!");
225         return isFileHandleResponse;
226     }
227     std::shared_ptr<std::string> sharedObject = event->GetSharedObject<std::string>();
228     if (sharedObject == nullptr) {
229         TELEPHONY_LOGE("sharedObject is nullptr!");
230         return isFileHandleResponse;
231     }
232     if (sharedObject != nullptr) {
233         imsi_ = *sharedObject;
234         TELEPHONY_LOGI("RuimFile::ProcessEvent MSG_SIM_OBTAIN_IMSI_DONE");
235         SaveCountryCode();
236         if (!imsi_.empty()) {
237             imsiReadyObser_->NotifyObserver(RadioEvent::RADIO_IMSI_LOADED_READY);
238             size_t imsiSize = imsi_.size();
239             std::string mcc = "";
240             bool isSizeEnough = imsiSize >= MCC_LEN;
241             if (isSizeEnough) {
242                 mcc = imsi_.substr(0, MCC_LEN);
243             }
244             std::string mnc = "";
245             isSizeEnough = imsiSize >= MCC_LEN + lengthOfMnc_;
246             if ((lengthOfMnc_ != UNINITIALIZED_MNC) && (lengthOfMnc_ != UNKNOWN_MNC) && isSizeEnough) {
247                 mnc = imsi_.substr(MCC_LEN, lengthOfMnc_);
248             }
249             if (!IsValidDecValue(mcc)) {
250                 TELEPHONY_LOGE("mcc is invalid decimal value");
251                 return false;
252             }
253             int mncLength = MccPool::ShortestMncLengthFromMcc(std::stoi(mcc));
254             isSizeEnough = imsiSize >= MCC_LEN + mncLength;
255             if (mnc.empty() && IsValidDecValue(mcc) && isSizeEnough) {
256                 mnc = imsi_.substr(MCC_LEN, mncLength);
257             }
258             AppExecFwk::Configuration configuration;
259             configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_MCC, mcc);
260             configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_MNC, mnc);
261             auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
262             appMgrClient->UpdateConfiguration(configuration);
263         }
264         FileChangeToExt(imsi_, FileChangeType::C_IMSI_FILE_LOAD);
265     }
266     return isFileHandleResponse;
267 }
268 
ObtainMdnNumber()269 std::string RuimFile::ObtainMdnNumber()
270 {
271     return phoneNumber_;
272 }
273 
ObtainCdmaMin()274 std::string RuimFile::ObtainCdmaMin()
275 {
276     return min2And1_;
277 }
278 
ObtainPrlVersion()279 std::string RuimFile::ObtainPrlVersion()
280 {
281     return prlVersion_;
282 }
283 
ObtainNAI()284 std::string RuimFile::ObtainNAI()
285 {
286     return nai_;
287 }
ObtainMdn()288 std::string RuimFile::ObtainMdn()
289 {
290     return mdn_;
291 }
292 
ObtainMin()293 std::string RuimFile::ObtainMin()
294 {
295     return min_;
296 }
297 
ObtainSid()298 std::string RuimFile::ObtainSid()
299 {
300     return systemId_;
301 }
302 
ObtainNid()303 std::string RuimFile::ObtainNid()
304 {
305     return networkId_;
306 }
307 
ObtainCsimSpnDisplayCondition()308 bool RuimFile::ObtainCsimSpnDisplayCondition()
309 {
310     return displayConditionOfCsimSpn_;
311 }
312 
InitMemberFunc()313 void RuimFile::InitMemberFunc()
314 {
315     memberFuncMap_[RadioEvent::RADIO_SIM_STATE_READY] =
316         [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessIccReady(event); };
317     memberFuncMap_[RadioEvent::RADIO_SIM_STATE_LOCKED] =
318         [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessIccLocked(event); };
319     memberFuncMap_[RadioEvent::RADIO_SIM_STATE_SIMLOCK] =
320         [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessIccLocked(event); };
321     memberFuncMap_[MSG_SIM_OBTAIN_IMSI_DONE] =
322         [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessGetImsiDone(event); };
323     memberFuncMap_[MSG_SIM_OBTAIN_ICCID_DONE] =
324         [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessGetIccidDone(event); };
325     memberFuncMap_[MSG_SIM_OBTAIN_CDMA_SUBSCRIPTION_DONE] =
326         [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessGetSubscriptionDone(event); };
327     memberFuncMap_[MSG_SIM_OBTAIN_CSIM_SPN_DONE] =
328         [this](const AppExecFwk::InnerEvent::Pointer &event) { return ProcessGetSpnDone(event); };
329 }
330 
ProcessGetSpnDone(const AppExecFwk::InnerEvent::Pointer &event)331 bool RuimFile::ProcessGetSpnDone(const AppExecFwk::InnerEvent::Pointer &event)
332 {
333     bool isFileProcessResponse = true;
334     if (event == nullptr) {
335         TELEPHONY_LOGE("event is nullptr!");
336         return isFileProcessResponse;
337     }
338     std::unique_ptr<ControllerToFileMsg> fd = event->GetUniqueObject<ControllerToFileMsg>();
339     if (fd == nullptr) {
340         TELEPHONY_LOGE("fd is nullptr!");
341         return isFileProcessResponse;
342     }
343     if (fd->exception != nullptr) {
344         TELEPHONY_LOGE("EfCsimSpnFileWanted ProcessParseFile get exception");
345         return isFileProcessResponse;
346     }
347     std::string iccData = fd->resultData;
348     if (iccData.empty()) {
349         TELEPHONY_LOGE("EfCsimSpnFileWanted ProcessParseFile get empty data");
350         return isFileProcessResponse;
351     }
352     int dataLen = 0;
353     std::shared_ptr<unsigned char> fileData = SIMUtils::HexStringConvertToBytes(iccData, dataLen);
354     unsigned char* data = fileData.get();
355     displayConditionOfCsimSpn_ = ((static_cast<unsigned int>(SPN_FLAG) & static_cast<unsigned int>(data[0])) != 0);
356 
357     int encoding = static_cast<int>(data[ENCODING_POS]);
358     int language = static_cast<int>(data[LANG_POS]);
359     unsigned char spnData[BUFFER_SIZE] = {0};
360 
361     int len = ((dataLen - FLAG_NUM) < MAX_DATA_BYTE) ? (dataLen - FLAG_NUM) : MAX_DATA_BYTE;
362     SIMUtils::ArrayCopy(data, FLAG_NUM, spnData, 0, len);
363 
364     int numBytes = 0;
365     int spnDataLen = strlen((char *)spnData);
366     for (numBytes = 0; numBytes < spnDataLen; numBytes++) {
367         if ((spnData[numBytes] & BYTE_NUM) == BYTE_NUM) {
368             break;
369         }
370     }
371 
372     if (numBytes == 0) {
373         UpdateSPN("");
374         return  isFileProcessResponse;
375     }
376     TELEPHONY_LOGI("EfCsimSpnFileWanted encoding is %{public}d, languange is %{public}d", encoding, language);
377     ParseSpnName(encoding, spnData, numBytes);
378     return  isFileProcessResponse;
379 }
ParseSpnName(int encodeType, const unsigned char* spnData, int dataLen)380 void RuimFile::ParseSpnName(int encodeType, const unsigned char* spnData, int dataLen)
381 {
382     switch (encodeType) {
383         case CSIM_SPN_OCTET:
384         case CSIM_SPN_LATIN: {
385             std::string spnName((char*)spnData, 0, dataLen);
386             UpdateSPN(spnName);
387             }
388             break;
389         case CSIM_SPN_IA5:
390         case CSIM_SPN_7BIT_ALPHABET: {
391             std::string spnName((char*)spnData, 0, dataLen);
392             UpdateSPN(spnName);
393             }
394             break;
395         case CSIM_SPN_7BIT_ASCII: {
396             std::string spnName((char*)spnData, 0, dataLen);
397             if (SIMUtils::IsShowableAsciiOnly(spnName)) {
398                 UpdateSPN(spnName);
399             } else {
400                 TELEPHONY_LOGI("EfCsimSpnFileWanted Some corruption in SPN decoding = %{public}s", spnName.data());
401             }
402             }
403             break;
404         case CSIM_SPN_UNICODE_16: {
405             int outlen = 0;
406             std::shared_ptr<char16_t> cs = SIMUtils::CharsConvertToChar16(spnData, dataLen, outlen, true);
407             std::u16string hs(cs.get(), 0, outlen);
408             std::string spnName = Str16ToStr8(hs);
409             TELEPHONY_LOGI("ENCODING_UNICODE_16 spn name = %{public}s", spnName.c_str());
410             UpdateSPN(spnName);
411             }
412             break;
413         default:
414             TELEPHONY_LOGI("SPN encoding not supported");
415     }
416 }
417 
ObtainSpnCondition(bool roaming, const std::string &operatorNum)418 int RuimFile::ObtainSpnCondition(bool roaming, const std::string &operatorNum)
419 {
420     return 0;
421 }
422 
UpdateVoiceMail(const std::string &mailName, const std::string &mailNumber)423 bool RuimFile::UpdateVoiceMail(const std::string &mailName, const std::string &mailNumber)
424 {
425     // cdma not support
426     return false;
427 }
428 
SetVoiceMailCount(int32_t voiceMailCount)429 bool RuimFile::SetVoiceMailCount(int32_t voiceMailCount)
430 {
431     // cdma not support
432     return false;
433 }
434 
SetVoiceCallForwarding(bool enable, const std::string &number)435 bool RuimFile::SetVoiceCallForwarding(bool enable, const std::string &number)
436 {
437     // cdma not support
438     return false;
439 }
440 
GetVoiceMailNumber()441 std::string RuimFile::GetVoiceMailNumber()
442 {
443     std::shared_lock<std::shared_mutex> lock(voiceMailMutex_);
444     return voiceMailNum_;
445 }
446 
SetVoiceMailNumber(const std::string mailNumber)447 void RuimFile::SetVoiceMailNumber(const std::string mailNumber)
448 {
449     std::unique_lock<std::shared_mutex> lock(voiceMailMutex_);
450     voiceMailNum_ = mailNumber;
451 }
452 
~RuimFile()453 RuimFile::~RuimFile() {}
454 } // namespace Telephony
455 } // namespace OHOS
456