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