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