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