1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.uicc; 18 19 import static android.telephony.SmsManager.STATUS_ON_ICC_READ; 20 import static android.telephony.SmsManager.STATUS_ON_ICC_UNREAD; 21 22 import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING; 23 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.content.Context; 26 import android.content.res.Resources; 27 import android.os.AsyncResult; 28 import android.os.Build; 29 import android.os.Message; 30 import android.os.PersistableBundle; 31 import android.telephony.CarrierConfigManager; 32 import android.telephony.PhoneNumberUtils; 33 import android.telephony.SmsMessage; 34 import android.telephony.SubscriptionInfo; 35 import android.telephony.SubscriptionManager; 36 import android.text.TextUtils; 37 import android.util.Log; 38 import android.util.Pair; 39 40 import com.android.internal.annotations.VisibleForTesting; 41 import com.android.internal.telephony.CommandsInterface; 42 import com.android.internal.telephony.MccTable; 43 import com.android.internal.telephony.SmsConstants; 44 import com.android.internal.telephony.gsm.SimTlv; 45 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType; 46 import com.android.telephony.Rlog; 47 48 import java.io.FileDescriptor; 49 import java.io.PrintWriter; 50 import java.util.ArrayList; 51 import java.util.Arrays; 52 import java.util.List; 53 import java.util.Objects; 54 55 /** 56 * {@hide} 57 */ 58 public class SIMRecords extends IccRecords { 59 protected static final String LOG_TAG = "SIMRecords"; 60 61 private static final boolean CRASH_RIL = false; 62 private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING || 63 Rlog.isLoggable(LOG_TAG, Log.VERBOSE); 64 65 // ***** Instance Variables 66 67 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 68 VoiceMailConstants mVmConfig; 69 70 // ***** Cached SIM State; cleared on channel close 71 72 private int mCallForwardingStatus; 73 74 /** 75 * States only used by getSpnFsm FSM 76 */ 77 private GetSpnFsmState mSpnState; 78 79 /** CPHS service information (See CPHS 4.2 B.3.1.1) 80 * It will be set in onSimReady if reading GET_CPHS_INFO successfully 81 * mCphsInfo[0] is CPHS Phase 82 * mCphsInfo[1] and mCphsInfo[2] is CPHS Service Table 83 */ 84 private byte[] mCphsInfo = null; 85 boolean mCspPlmnEnabled = true; 86 87 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 88 byte[] mEfMWIS = null; 89 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 90 byte[] mEfCPHS_MWI =null; 91 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 92 byte[] mEfCff = null; 93 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 94 byte[] mEfCfis = null; 95 96 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 97 byte[] mEfLi = null; 98 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 99 byte[] mEfPl = null; 100 101 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 102 UsimServiceTable mUsimServiceTable; 103 104 @Override toString()105 public String toString() { 106 return "SimRecords: " + super.toString() 107 + " mVmConfig" + mVmConfig 108 + " callForwardingEnabled=" + mCallForwardingStatus 109 + " spnState=" + mSpnState 110 + " mCphsInfo=" + IccUtils.bytesToHexString(mCphsInfo) 111 + " mCspPlmnEnabled=" + mCspPlmnEnabled 112 + " efMWIS=" + IccUtils.bytesToHexString(mEfMWIS) 113 + " efCPHS_MWI=" + IccUtils.bytesToHexString(mEfCPHS_MWI) 114 + " mEfCff=" + IccUtils.bytesToHexString(mEfCff) 115 + " mEfCfis=" + IccUtils.bytesToHexString(mEfCfis) 116 + " getOperatorNumeric=" + getOperatorNumeric() 117 + " mPsiSmsc=" + mPsiSmsc 118 + " TPMR=" + getSmssTpmrValue(); 119 } 120 121 // ***** Constants 122 123 // From TS 51.011 EF[SPDI] section 124 static final int TAG_SPDI = 0xA3; 125 static final int TAG_SPDI_PLMN_LIST = 0x80; 126 127 // Full Name IEI from TS 24.008 128 static final int TAG_FULL_NETWORK_NAME = 0x43; 129 130 // Short Name IEI from TS 24.008 131 static final int TAG_SHORT_NETWORK_NAME = 0x45; 132 133 // PLMN Additional Information tag from from TS 24.008 134 static final int TAG_PLMN_ADDITIONAL_INFORMATION = 0x80; 135 136 // active CFF from CPHS 4.2 B.4.5 137 static final int CFF_UNCONDITIONAL_ACTIVE = 0x0a; 138 static final int CFF_UNCONDITIONAL_DEACTIVE = 0x05; 139 static final int CFF_LINE1_MASK = 0x0f; 140 static final int CFF_LINE1_RESET = 0xf0; 141 142 // CPHS Service Table (See CPHS 4.2 B.3.1) 143 private static final int CPHS_SST_MBN_MASK = 0x30; 144 private static final int CPHS_SST_MBN_ENABLED = 0x30; 145 146 // EF_CFIS related constants 147 // Spec reference TS 51.011 section 10.3.46. 148 private static final int CFIS_BCD_NUMBER_LENGTH_OFFSET = 2; 149 private static final int CFIS_TON_NPI_OFFSET = 3; 150 private static final int CFIS_ADN_CAPABILITY_ID_OFFSET = 14; 151 private static final int CFIS_ADN_EXTENSION_ID_OFFSET = 15; 152 153 // 3GPP specification constants 154 // Spec reference TS 31.102 section 4.2.16 155 private static final int FPLMN_BYTE_SIZE = 3; 156 157 // ***** Event Constants 158 private static final int SIM_RECORD_EVENT_BASE = 0x00; 159 private static final int EVENT_GET_IMSI_DONE = 3 + SIM_RECORD_EVENT_BASE; 160 private static final int EVENT_GET_ICCID_DONE = 4 + SIM_RECORD_EVENT_BASE; 161 private static final int EVENT_GET_MBI_DONE = 5 + SIM_RECORD_EVENT_BASE; 162 private static final int EVENT_GET_MBDN_DONE = 6 + SIM_RECORD_EVENT_BASE; 163 private static final int EVENT_GET_MWIS_DONE = 7 + SIM_RECORD_EVENT_BASE; 164 private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8 + SIM_RECORD_EVENT_BASE; 165 private static final int EVENT_GET_AD_DONE = 9 + SIM_RECORD_EVENT_BASE; // Admin data on SIM 166 private static final int EVENT_GET_MSISDN_DONE = 10 + SIM_RECORD_EVENT_BASE; 167 private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11 + SIM_RECORD_EVENT_BASE; 168 private static final int EVENT_GET_SPN_DONE = 12 + SIM_RECORD_EVENT_BASE; 169 private static final int EVENT_GET_SPDI_DONE = 13 + SIM_RECORD_EVENT_BASE; 170 private static final int EVENT_UPDATE_DONE = 14 + SIM_RECORD_EVENT_BASE; 171 protected static final int EVENT_GET_PNN_DONE = 15 + SIM_RECORD_EVENT_BASE; 172 protected static final int EVENT_GET_OPL_DONE = 16 + SIM_RECORD_EVENT_BASE; 173 protected static final int EVENT_GET_SST_DONE = 17 + SIM_RECORD_EVENT_BASE; 174 private static final int EVENT_GET_ALL_SMS_DONE = 18 + SIM_RECORD_EVENT_BASE; 175 private static final int EVENT_MARK_SMS_READ_DONE = 19 + SIM_RECORD_EVENT_BASE; 176 private static final int EVENT_SET_MBDN_DONE = 20 + SIM_RECORD_EVENT_BASE; 177 private static final int EVENT_SMS_ON_SIM = 21 + SIM_RECORD_EVENT_BASE; 178 private static final int EVENT_GET_SMS_DONE = 22 + SIM_RECORD_EVENT_BASE; 179 private static final int EVENT_GET_CFF_DONE = 24 + SIM_RECORD_EVENT_BASE; 180 private static final int EVENT_SET_CPHS_MAILBOX_DONE = 25 + SIM_RECORD_EVENT_BASE; 181 private static final int EVENT_GET_INFO_CPHS_DONE = 26 + SIM_RECORD_EVENT_BASE; 182 private static final int EVENT_SET_MSISDN_DONE = 30 + SIM_RECORD_EVENT_BASE; 183 private static final int EVENT_GET_CFIS_DONE = 32 + SIM_RECORD_EVENT_BASE; 184 private static final int EVENT_GET_CSP_CPHS_DONE = 33 + SIM_RECORD_EVENT_BASE; 185 private static final int EVENT_GET_GID1_DONE = 34 + SIM_RECORD_EVENT_BASE; 186 private static final int EVENT_GET_GID2_DONE = 36 + SIM_RECORD_EVENT_BASE; 187 private static final int EVENT_GET_PLMN_W_ACT_DONE = 37 + SIM_RECORD_EVENT_BASE; 188 private static final int EVENT_GET_OPLMN_W_ACT_DONE = 38 + SIM_RECORD_EVENT_BASE; 189 private static final int EVENT_GET_HPLMN_W_ACT_DONE = 39 + SIM_RECORD_EVENT_BASE; 190 private static final int EVENT_GET_EHPLMN_DONE = 40 + SIM_RECORD_EVENT_BASE; 191 private static final int EVENT_GET_FPLMN_DONE = 41 + SIM_RECORD_EVENT_BASE; 192 private static final int EVENT_GET_FPLMN_SIZE_DONE = 42 + SIM_RECORD_EVENT_BASE; 193 private static final int EVENT_SET_FPLMN_DONE = 43 + SIM_RECORD_EVENT_BASE; 194 protected static final int EVENT_GET_SMSS_RECORD_DONE = 46 + SIM_RECORD_EVENT_BASE; 195 protected static final int EVENT_GET_PSISMSC_DONE = 47 + SIM_RECORD_EVENT_BASE; 196 197 // ***** Constructor 198 SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci)199 public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) { 200 super(app, c, ci); 201 202 mAdnCache = new AdnRecordCache(mFh); 203 204 mVmConfig = new VoiceMailConstants(); 205 206 mRecordsRequested = false; // No load request is made till SIM ready 207 mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE; 208 209 // recordsToLoad is set to 0 because no requests are made yet 210 mRecordsToLoad = 0; 211 212 mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null); 213 214 // Start off by setting empty state 215 resetRecords(); 216 if (DBG) log("SIMRecords X ctor this=" + this); 217 } 218 219 @Override dispose()220 public void dispose() { 221 if (DBG) log("Disposing SIMRecords this=" + this); 222 //Unregister for all events 223 mCi.unSetOnSmsOnSim(this); 224 resetRecords(); 225 super.dispose(); 226 } 227 228 @Override finalize()229 protected void finalize() { 230 if (DBG) log("finalized"); 231 } 232 resetRecords()233 protected void resetRecords() { 234 mImsi = null; 235 mMsisdn = null; 236 mVoiceMailNum = null; 237 mMncLength = UNINITIALIZED; 238 log("setting0 mMncLength" + mMncLength); 239 mIccId = null; 240 mFullIccId = null; 241 mCarrierNameDisplayCondition = DEFAULT_CARRIER_NAME_DISPLAY_CONDITION; 242 mEfMWIS = null; 243 mEfCPHS_MWI = null; 244 mSpdi = null; 245 mPnnHomeName = null; 246 mPnns = null; 247 mOpl = null; 248 mGid1 = null; 249 mGid2 = null; 250 mPlmnActRecords = null; 251 mOplmnActRecords = null; 252 mHplmnActRecords = null; 253 mFplmns = null; 254 mEhplmns = null; 255 256 mAdnCache.reset(); 257 258 log("SIMRecords: onRadioOffOrNotAvailable set 'gsm.sim.operator.numeric' to operator=null"); 259 log("update icc_operator_numeric=" + null); 260 mTelephonyManager.setSimOperatorNumericForPhone(mParentApp.getPhoneId(), ""); 261 mTelephonyManager.setSimOperatorNameForPhone(mParentApp.getPhoneId(), ""); 262 mTelephonyManager.setSimCountryIsoForPhone(mParentApp.getPhoneId(), ""); 263 264 // recordsRequested is set to false indicating that the SIM 265 // read requests made so far are not valid. This is set to 266 // true only when fresh set of read requests are made. 267 mRecordsRequested = false; 268 mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE; 269 mLoaded.set(false); 270 } 271 272 //***** Public Methods 273 274 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 275 @Override getMsisdnNumber()276 public String getMsisdnNumber() { 277 return mMsisdn; 278 } 279 280 @Override getUsimServiceTable()281 public UsimServiceTable getUsimServiceTable() { 282 return mUsimServiceTable; 283 } 284 285 /** 286 * Fetches the USIM service table from UsimServiceTable 287 * 288 * @return HexString representation of USIM service table 289 */ getSimServiceTable()290 public String getSimServiceTable() { 291 if (mUsimServiceTable != null) { 292 return IccUtils.bytesToHexString(mUsimServiceTable.getUSIMServiceTable()); 293 } 294 return null; 295 } 296 297 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getExtFromEf(int ef)298 private int getExtFromEf(int ef) { 299 int ext; 300 switch (ef) { 301 case EF_FDN: return EF_EXT2; 302 case EF_MSISDN: 303 /* For USIM apps use EXT5. (TS 31.102 Section 4.2.37) */ 304 if (mParentApp.getType() == AppType.APPTYPE_USIM) { 305 ext = EF_EXT5; 306 } else { 307 ext = EF_EXT1; 308 } 309 break; 310 default: 311 ext = EF_EXT1; 312 } 313 return ext; 314 } 315 316 /** 317 * Set subscriber number to SIM record 318 * 319 * The subscriber number is stored in EF_MSISDN (TS 51.011) 320 * 321 * When the operation is complete, onComplete will be sent to its handler 322 * 323 * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters) 324 * @param number dialing number (up to 20 digits) 325 * if the number starts with '+', then set to international TOA 326 * @param onComplete 327 * onComplete.obj will be an AsyncResult 328 * ((AsyncResult)onComplete.obj).exception == null on success 329 * ((AsyncResult)onComplete.obj).exception != null on fail 330 */ 331 @Override setMsisdnNumber(String alphaTag, String number, Message onComplete)332 public void setMsisdnNumber(String alphaTag, String number, 333 Message onComplete) { 334 if (mDestroyed.get()) { 335 return; 336 } 337 // If the SIM card is locked by PIN, we will set EF_MSISDN fail. 338 // In that case, msisdn and msisdnTag should not be update. 339 mNewMsisdn = number; 340 mNewMsisdnTag = alphaTag; 341 342 if(DBG) log("Set MSISDN: " + mNewMsisdnTag + " " + /*mNewMsisdn*/ 343 Rlog.pii(LOG_TAG, mNewMsisdn)); 344 345 AdnRecord adn = new AdnRecord(mNewMsisdnTag, mNewMsisdn); 346 347 new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, getExtFromEf(EF_MSISDN), 1, null, 348 obtainMessage(EVENT_SET_MSISDN_DONE, onComplete)); 349 } 350 351 @Override getMsisdnAlphaTag()352 public String getMsisdnAlphaTag() { 353 return mMsisdnTag; 354 } 355 356 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 357 @Override getVoiceMailNumber()358 public String getVoiceMailNumber() { 359 return mVoiceMailNum; 360 } 361 362 /** 363 * Set voice mail number to SIM record 364 * 365 * The voice mail number can be stored either in EF_MBDN (TS 51.011) or 366 * EF_MAILBOX_CPHS (CPHS 4.2) 367 * 368 * If EF_MBDN is available, store the voice mail number to EF_MBDN 369 * 370 * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS 371 * 372 * So the voice mail number will be stored in both EFs if both are available 373 * 374 * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail. 375 * 376 * When the operation is complete, onComplete will be sent to its handler 377 * 378 * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters) 379 * @param voiceNumber dailing nubmer (upto 20 digits) 380 * if the number is start with '+', then set to international TOA 381 * @param onComplete 382 * onComplete.obj will be an AsyncResult 383 * ((AsyncResult)onComplete.obj).exception == null on success 384 * ((AsyncResult)onComplete.obj).exception != null on fail 385 */ 386 @Override setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete)387 public void setVoiceMailNumber(String alphaTag, String voiceNumber, 388 Message onComplete) { 389 if (mDestroyed.get()) { 390 return; 391 } 392 393 if (mIsVoiceMailFixed) { 394 AsyncResult.forMessage((onComplete)).exception = 395 new IccVmFixedException("Voicemail number is fixed by operator"); 396 onComplete.sendToTarget(); 397 return; 398 } 399 400 mNewVoiceMailNum = voiceNumber; 401 mNewVoiceMailTag = alphaTag; 402 403 AdnRecord adn = new AdnRecord(mNewVoiceMailTag, mNewVoiceMailNum); 404 if (mMailboxIndex != 0 && mMailboxIndex != 0xff) { 405 406 new AdnRecordLoader(mFh).updateEF(adn, EF_MBDN, EF_EXT6, 407 mMailboxIndex, null, 408 obtainMessage(EVENT_SET_MBDN_DONE, AdnRecordLoader.VOICEMAIL_ALPHATAG_ARG, 409 0 /* ignored arg2 */, onComplete)); 410 411 } else if (isCphsMailboxEnabled()) { 412 413 new AdnRecordLoader(mFh).updateEF(adn, EF_MAILBOX_CPHS, 414 EF_EXT1, 1, null, 415 obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE, 416 AdnRecordLoader.VOICEMAIL_ALPHATAG_ARG, 417 0 /* ignored arg2 */, onComplete)); 418 419 } else { 420 AsyncResult.forMessage((onComplete)).exception = 421 new IccVmNotSupportedException("Update SIM voice mailbox error"); 422 onComplete.sendToTarget(); 423 } 424 } 425 426 @Override getVoiceMailAlphaTag()427 public String getVoiceMailAlphaTag() 428 { 429 return mVoiceMailTag; 430 } 431 432 /** 433 * Sets the SIM voice message waiting indicator records 434 * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported 435 * @param countWaiting The number of messages waiting, if known. Use 436 * -1 to indicate that an unknown number of 437 * messages are waiting 438 */ 439 @Override 440 public void setVoiceMessageWaiting(int line, int countWaiting)441 setVoiceMessageWaiting(int line, int countWaiting) { 442 if (mDestroyed.get()) { 443 return; 444 } 445 if (line != 1) { 446 // only profile 1 is supported 447 return; 448 } 449 450 try { 451 if (mEfMWIS != null) { 452 // TS 51.011 10.3.45 453 454 // lsb of byte 0 is 'voicemail' status 455 mEfMWIS[0] = (byte)((mEfMWIS[0] & 0xfe) 456 | (countWaiting == 0 ? 0 : 1)); 457 458 // byte 1 is the number of voice messages waiting 459 if (countWaiting < 0) { 460 // The spec does not define what this should be 461 // if we don't know the count 462 mEfMWIS[1] = 0; 463 } else { 464 mEfMWIS[1] = (byte) countWaiting; 465 } 466 467 mFh.updateEFLinearFixed( 468 EF_MWIS, 1, mEfMWIS, null, 469 obtainMessage (EVENT_UPDATE_DONE, EF_MWIS, 0)); 470 } 471 472 if (mEfCPHS_MWI != null) { 473 // Refer CPHS4_2.WW6 B4.2.3 474 mEfCPHS_MWI[0] = (byte)((mEfCPHS_MWI[0] & 0xf0) 475 | (countWaiting == 0 ? 0x5 : 0xa)); 476 mFh.updateEFTransparent( 477 EF_VOICE_MAIL_INDICATOR_CPHS, mEfCPHS_MWI, 478 obtainMessage (EVENT_UPDATE_DONE, EF_VOICE_MAIL_INDICATOR_CPHS)); 479 } 480 } catch (ArrayIndexOutOfBoundsException ex) { 481 logw("Error saving voice mail state to SIM. Probably malformed SIM record", ex); 482 } 483 } 484 485 // Validate data is not null and not empty. validEfCfis(byte[] data)486 private boolean validEfCfis(byte[] data) { 487 if (data != null) { 488 if (data[0] < 1 || data[0] > 4) { 489 // The MSP (Multiple Subscriber Profile) byte should be between 490 // 1 and 4 according to ETSI TS 131 102 v11.3.0 section 4.2.64. 491 logw("MSP byte: " + data[0] + " is not between 1 and 4", null); 492 } 493 // empty EF_CFIS should be considered as call forward disabled 494 for (byte b : data) { 495 if (b != (byte) 0xFF) { 496 return true; 497 } 498 } 499 } 500 return false; 501 } 502 getVoiceMessageCount()503 public int getVoiceMessageCount() { 504 boolean voiceMailWaiting = false; 505 int countVoiceMessages = DEFAULT_VOICE_MESSAGE_COUNT; 506 if (mEfMWIS != null) { 507 // Use this data if the EF[MWIS] exists and 508 // has been loaded 509 // Refer TS 51.011 Section 10.3.45 for the content description 510 voiceMailWaiting = ((mEfMWIS[0] & 0x01) != 0); 511 countVoiceMessages = mEfMWIS[1] & 0xff; 512 513 if (voiceMailWaiting && (countVoiceMessages == 0 || countVoiceMessages == 0xff)) { 514 // Unknown count = -1 515 countVoiceMessages = UNKNOWN_VOICE_MESSAGE_COUNT; 516 } 517 if (DBG) log(" VoiceMessageCount from SIM MWIS = " + countVoiceMessages); 518 } else if (mEfCPHS_MWI != null) { 519 // use voice mail count from CPHS 520 int indicator = (int) (mEfCPHS_MWI[0] & 0xf); 521 522 // Refer CPHS4_2.WW6 B4.2.3 523 if (indicator == 0xA) { 524 // Unknown count = -1 525 countVoiceMessages = UNKNOWN_VOICE_MESSAGE_COUNT; 526 } else if (indicator == 0x5) { 527 countVoiceMessages = 0; 528 } 529 if (DBG) log(" VoiceMessageCount from SIM CPHS = " + countVoiceMessages); 530 } 531 return countVoiceMessages; 532 } 533 534 /** 535 * {@inheritDoc} 536 */ 537 @Override getVoiceCallForwardingFlag()538 public int getVoiceCallForwardingFlag() { 539 return mCallForwardingStatus; 540 } 541 542 /** 543 * {@inheritDoc} 544 */ 545 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 546 @Override setVoiceCallForwardingFlag(int line, boolean enable, String dialNumber)547 public void setVoiceCallForwardingFlag(int line, boolean enable, String dialNumber) { 548 if (mDestroyed.get()) { 549 return; 550 } 551 if (line != 1) return; // only line 1 is supported 552 553 mCallForwardingStatus = enable ? CALL_FORWARDING_STATUS_ENABLED : 554 CALL_FORWARDING_STATUS_DISABLED; 555 556 mRecordsEventsRegistrants.notifyResult(EVENT_CFI); 557 558 try { 559 if (validEfCfis(mEfCfis)) { 560 // lsb is of byte f1 is voice status 561 if (enable) { 562 mEfCfis[1] |= 1; 563 } else { 564 mEfCfis[1] &= 0xfe; 565 } 566 567 log("setVoiceCallForwardingFlag: enable=" + enable 568 + " mEfCfis=" + IccUtils.bytesToHexString(mEfCfis)); 569 570 // Update dialNumber if not empty and CFU is enabled. 571 // Spec reference for EF_CFIS contents, TS 51.011 section 10.3.46. 572 if (enable && !TextUtils.isEmpty(dialNumber)) { 573 logv("EF_CFIS: updating cf number, " + Rlog.pii(LOG_TAG, dialNumber)); 574 byte[] bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD( 575 dialNumber, PhoneNumberUtils.BCD_EXTENDED_TYPE_EF_ADN); 576 577 System.arraycopy(bcdNumber, 0, mEfCfis, CFIS_TON_NPI_OFFSET, bcdNumber.length); 578 579 mEfCfis[CFIS_BCD_NUMBER_LENGTH_OFFSET] = (byte) (bcdNumber.length); 580 mEfCfis[CFIS_ADN_CAPABILITY_ID_OFFSET] = (byte) 0xFF; 581 mEfCfis[CFIS_ADN_EXTENSION_ID_OFFSET] = (byte) 0xFF; 582 } 583 584 mFh.updateEFLinearFixed( 585 EF_CFIS, 1, mEfCfis, null, 586 obtainMessage (EVENT_UPDATE_DONE, EF_CFIS)); 587 } else { 588 log("setVoiceCallForwardingFlag: ignoring enable=" + enable 589 + " invalid mEfCfis=" + IccUtils.bytesToHexString(mEfCfis)); 590 } 591 592 if (mEfCff != null) { 593 if (enable) { 594 mEfCff[0] = (byte) ((mEfCff[0] & CFF_LINE1_RESET) 595 | CFF_UNCONDITIONAL_ACTIVE); 596 } else { 597 mEfCff[0] = (byte) ((mEfCff[0] & CFF_LINE1_RESET) 598 | CFF_UNCONDITIONAL_DEACTIVE); 599 } 600 601 mFh.updateEFTransparent( 602 EF_CFF_CPHS, mEfCff, 603 obtainMessage (EVENT_UPDATE_DONE, EF_CFF_CPHS)); 604 } 605 } catch (ArrayIndexOutOfBoundsException ex) { 606 logw("Error saving call forwarding flag to SIM. " 607 + "Probably malformed SIM record", ex); 608 609 } 610 } 611 612 /** 613 * Called by STK Service when REFRESH is received. 614 * @param fileChanged indicates whether any files changed 615 * @param fileList if non-null, a list of EF files that changed 616 */ 617 @Override onRefresh(boolean fileChanged, int[] fileList)618 public void onRefresh(boolean fileChanged, int[] fileList) { 619 if (fileChanged) { 620 // A future optimization would be to inspect fileList and 621 // only reload those files that we care about. For now, 622 // just re-fetch all SIM records that we cache. 623 fetchSimRecords(); 624 } 625 } 626 627 /** 628 * {@inheritDoc} 629 */ 630 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 631 @Override getOperatorNumeric()632 public String getOperatorNumeric() { 633 String imsi = getIMSI(); 634 if (imsi == null) { 635 log("getOperatorNumeric: IMSI == null"); 636 return null; 637 } 638 if (mMncLength == UNINITIALIZED || mMncLength == UNKNOWN) { 639 log("getSIMOperatorNumeric: bad mncLength"); 640 return null; 641 } 642 643 // Length = length of MCC + length of MNC 644 // length of mcc = 3 (TS 23.003 Section 2.2) 645 if (imsi.length() >= 3 + mMncLength) { 646 return imsi.substring(0, 3 + mMncLength); 647 } else { 648 return null; 649 } 650 } 651 652 // ***** Overridden from Handler 653 @Override handleMessage(Message msg)654 public void handleMessage(Message msg) { 655 AsyncResult ar; 656 AdnRecord adn; 657 658 byte data[]; 659 660 boolean isRecordLoadResponse = false; 661 662 if (mDestroyed.get()) { 663 loge("Received message " + msg + "[" + msg.what + "] " + 664 " while being destroyed. Ignoring."); 665 return; 666 } 667 try { 668 switch (msg.what) { 669 /* IO events */ 670 case EVENT_GET_IMSI_DONE: 671 isRecordLoadResponse = true; 672 ar = (AsyncResult) msg.obj; 673 674 if (ar.exception != null) { 675 loge("Exception querying IMSI, Exception:" + ar.exception); 676 break; 677 } 678 679 setImsi((String) ar.result); 680 break; 681 682 case EVENT_GET_MBI_DONE: 683 boolean isValidMbdn; 684 isRecordLoadResponse = true; 685 686 ar = (AsyncResult) msg.obj; 687 data = (byte[]) ar.result; 688 689 isValidMbdn = false; 690 if (ar.exception == null) { 691 // Refer TS 51.011 Section 10.3.44 for content details 692 log("EF_MBI: " + IccUtils.bytesToHexString(data)); 693 694 // Voice mail record number stored first 695 mMailboxIndex = data[0] & 0xff; 696 697 // check if dailing numbe id valid 698 if (mMailboxIndex != 0 && mMailboxIndex != 0xff) { 699 log("Got valid mailbox number for MBDN"); 700 isValidMbdn = true; 701 } 702 } 703 704 // one more record to load 705 mRecordsToLoad += 1; 706 707 if (isValidMbdn) { 708 // Note: MBDN was not included in NUM_OF_SIM_RECORDS_LOADED 709 new AdnRecordLoader(mFh).loadFromEF(EF_MBDN, EF_EXT6, 710 mMailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE)); 711 } else { 712 // If this EF not present, try mailbox as in CPHS standard 713 // CPHS (CPHS4_2.WW6) is a european standard. 714 new AdnRecordLoader(mFh).loadFromEF(EF_MAILBOX_CPHS, 715 EF_EXT1, 1, 716 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE)); 717 } 718 719 break; 720 case EVENT_GET_CPHS_MAILBOX_DONE: 721 case EVENT_GET_MBDN_DONE: 722 //Resetting the voice mail number and voice mail tag to null 723 //as these should be updated from the data read from EF_MBDN. 724 //If they are not reset, incase of invalid data/exception these 725 //variables are retaining their previous values and are 726 //causing invalid voice mailbox info display to user. 727 mVoiceMailNum = null; 728 mVoiceMailTag = null; 729 isRecordLoadResponse = true; 730 731 ar = (AsyncResult) msg.obj; 732 733 if (ar.exception != null) { 734 735 log("Invalid or missing EF" 736 + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) 737 ? "[MAILBOX]" : "[MBDN]")); 738 739 // Bug #645770 fall back to CPHS 740 // FIXME should use SST to decide 741 742 if (msg.what == EVENT_GET_MBDN_DONE) { 743 //load CPHS on fail... 744 // FIXME right now, only load line1's CPHS voice mail entry 745 746 mRecordsToLoad += 1; 747 new AdnRecordLoader(mFh).loadFromEF( 748 EF_MAILBOX_CPHS, EF_EXT1, 1, 749 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE)); 750 } 751 break; 752 } 753 754 adn = (AdnRecord) ar.result; 755 756 log("VM: " + adn 757 + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) 758 ? " EF[MAILBOX]" : " EF[MBDN]")); 759 760 if (adn.isEmpty() && msg.what == EVENT_GET_MBDN_DONE) { 761 // Bug #645770 fall back to CPHS 762 // FIXME should use SST to decide 763 // FIXME right now, only load line1's CPHS voice mail entry 764 mRecordsToLoad += 1; 765 new AdnRecordLoader(mFh).loadFromEF( 766 EF_MAILBOX_CPHS, EF_EXT1, 1, 767 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE)); 768 769 break; 770 } 771 772 mVoiceMailNum = adn.getNumber(); 773 mVoiceMailTag = adn.getAlphaTag(); 774 break; 775 776 case EVENT_GET_MSISDN_DONE: 777 isRecordLoadResponse = true; 778 779 ar = (AsyncResult) msg.obj; 780 781 if (ar.exception != null) { 782 log("Invalid or missing EF[MSISDN]"); 783 break; 784 } 785 786 adn = (AdnRecord) ar.result; 787 788 mMsisdn = adn.getNumber(); 789 mMsisdnTag = adn.getAlphaTag(); 790 791 log("MSISDN: " + /*mMsisdn*/ Rlog.pii(LOG_TAG, mMsisdn)); 792 break; 793 794 case EVENT_SET_MSISDN_DONE: 795 isRecordLoadResponse = false; 796 ar = (AsyncResult) msg.obj; 797 798 if (ar.exception == null) { 799 mMsisdn = mNewMsisdn; 800 mMsisdnTag = mNewMsisdnTag; 801 log("Success to update EF[MSISDN]"); 802 } 803 804 if (ar.userObj != null) { 805 AsyncResult.forMessage(((Message) ar.userObj)).exception = ar.exception; 806 ((Message) ar.userObj).sendToTarget(); 807 } 808 break; 809 810 case EVENT_GET_MWIS_DONE: 811 isRecordLoadResponse = true; 812 813 ar = (AsyncResult) msg.obj; 814 data = (byte[]) ar.result; 815 816 if (DBG) log("EF_MWIS : " + IccUtils.bytesToHexString(data)); 817 818 if (ar.exception != null) { 819 if (DBG) log("EVENT_GET_MWIS_DONE exception = " + ar.exception); 820 break; 821 } 822 823 if ((data[0] & 0xff) == 0xff) { 824 if (DBG) log("SIMRecords: Uninitialized record MWIS"); 825 break; 826 } 827 828 mEfMWIS = data; 829 break; 830 831 case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE: 832 isRecordLoadResponse = true; 833 834 ar = (AsyncResult) msg.obj; 835 data = (byte[]) ar.result; 836 837 if (DBG) log("EF_CPHS_MWI: " + IccUtils.bytesToHexString(data)); 838 839 if (ar.exception != null) { 840 if (DBG) { 841 log("EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE exception = " 842 + ar.exception); 843 } 844 break; 845 } 846 847 mEfCPHS_MWI = data; 848 break; 849 850 case EVENT_GET_ICCID_DONE: 851 isRecordLoadResponse = true; 852 853 ar = (AsyncResult) msg.obj; 854 data = (byte[]) ar.result; 855 856 if (ar.exception != null) { 857 break; 858 } 859 860 mIccId = IccUtils.bcdToString(data, 0, data.length); 861 mFullIccId = IccUtils.bchToString(data, 0, data.length); 862 863 log("iccid: " + SubscriptionInfo.getPrintableId(mFullIccId)); 864 break; 865 866 case EVENT_GET_AD_DONE: 867 isRecordLoadResponse = true; 868 mMncLength = UNKNOWN; 869 try { 870 if (!mCarrierTestOverride.isInTestMode()) { 871 ar = (AsyncResult) msg.obj; 872 data = (byte[]) ar.result; 873 874 if (ar.exception != null) { 875 break; 876 } 877 878 log("EF_AD: " + IccUtils.bytesToHexString(data)); 879 880 if (data.length < 3) { 881 log("Corrupt AD data on SIM"); 882 break; 883 } 884 885 if (data.length == 3) { 886 log("MNC length not present in EF_AD"); 887 break; 888 } 889 890 int len = data[3] & 0xf; 891 if (len == 2 || len == 3) { 892 mMncLength = len; 893 } else { 894 log("Received invalid or unset MNC Length=" + len); 895 } 896 } 897 } finally { 898 updateOperatorPlmn(); 899 } 900 break; 901 902 case EVENT_GET_SPN_DONE: 903 isRecordLoadResponse = true; 904 ar = (AsyncResult) msg.obj; 905 getSpnFsm(false, ar); 906 break; 907 908 case EVENT_GET_CFF_DONE: 909 isRecordLoadResponse = true; 910 911 ar = (AsyncResult) msg.obj; 912 data = (byte[]) ar.result; 913 914 if (ar.exception != null) { 915 mEfCff = null; 916 } else { 917 log("EF_CFF_CPHS: " + IccUtils.bytesToHexString(data)); 918 mEfCff = data; 919 } 920 921 break; 922 923 case EVENT_GET_SPDI_DONE: 924 isRecordLoadResponse = true; 925 926 ar = (AsyncResult) msg.obj; 927 data = (byte[]) ar.result; 928 929 if (ar.exception != null) { 930 break; 931 } 932 933 parseEfSpdi(data); 934 break; 935 936 case EVENT_UPDATE_DONE: 937 ar = (AsyncResult) msg.obj; 938 if (ar.exception != null) { 939 logw("update failed. ", ar.exception); 940 } 941 break; 942 943 case EVENT_GET_PNN_DONE: 944 isRecordLoadResponse = true; 945 946 ar = (AsyncResult) msg.obj; 947 if (ar.exception != null) { 948 break; 949 } 950 951 parseEfPnn((ArrayList<byte[]>) ar.result); 952 break; 953 954 case EVENT_GET_OPL_DONE: 955 isRecordLoadResponse = true; 956 957 ar = (AsyncResult) msg.obj; 958 if (ar.exception != null) { 959 break; 960 } 961 962 parseEfOpl((ArrayList<byte[]>) ar.result); 963 break; 964 965 case EVENT_GET_ALL_SMS_DONE: 966 isRecordLoadResponse = true; 967 968 ar = (AsyncResult) msg.obj; 969 if (ar.exception != null) { 970 break; 971 } 972 973 handleSmses((ArrayList<byte[]>) ar.result); 974 break; 975 976 case EVENT_MARK_SMS_READ_DONE: 977 log("marked read: sms " + msg.arg1); 978 break; 979 980 981 case EVENT_SMS_ON_SIM: 982 isRecordLoadResponse = false; 983 984 ar = (AsyncResult) msg.obj; 985 986 Integer index = (Integer) ar.result; 987 988 if (ar.exception != null || index == null) { 989 loge("Error on SMS_ON_SIM with exp " 990 + ar.exception + " index " + index); 991 } else { 992 log("READ EF_SMS RECORD index=" + index); 993 mFh.loadEFLinearFixed(EF_SMS, index, obtainMessage(EVENT_GET_SMS_DONE)); 994 } 995 break; 996 997 case EVENT_GET_SMS_DONE: 998 isRecordLoadResponse = false; 999 ar = (AsyncResult) msg.obj; 1000 if (ar.exception == null) { 1001 handleSms((byte[]) ar.result); 1002 } else { 1003 loge("Error on GET_SMS with exp " + ar.exception); 1004 } 1005 break; 1006 case EVENT_GET_SST_DONE: 1007 isRecordLoadResponse = true; 1008 1009 ar = (AsyncResult) msg.obj; 1010 data = (byte[]) ar.result; 1011 1012 if (ar.exception != null) { 1013 break; 1014 } 1015 1016 mUsimServiceTable = new UsimServiceTable(data); 1017 if (DBG) log("SST: " + mUsimServiceTable); 1018 break; 1019 1020 case EVENT_GET_INFO_CPHS_DONE: 1021 isRecordLoadResponse = true; 1022 1023 ar = (AsyncResult) msg.obj; 1024 1025 if (ar.exception != null) { 1026 break; 1027 } 1028 1029 mCphsInfo = (byte[]) ar.result; 1030 1031 if (DBG) log("iCPHS: " + IccUtils.bytesToHexString(mCphsInfo)); 1032 break; 1033 1034 case EVENT_SET_MBDN_DONE: 1035 isRecordLoadResponse = false; 1036 ar = (AsyncResult) msg.obj; 1037 1038 if (DBG) log("EVENT_SET_MBDN_DONE ex:" + ar.exception); 1039 if (ar.exception == null) { 1040 /** 1041 * Check for any changes made to voicemail alphaTag while saving to SIM. 1042 * if voicemail alphaTag length is more than allowed limit of SIM EF then 1043 * null alphaTag will be saved to SIM {@code AdnRecordLoader}. 1044 */ 1045 if (ar.result != null) { 1046 AdnRecord adnRecord = (AdnRecord) (ar.result); 1047 if (adnRecord != null) { 1048 mNewVoiceMailTag = adnRecord.mAlphaTag; 1049 } 1050 } 1051 mVoiceMailNum = mNewVoiceMailNum; 1052 mVoiceMailTag = mNewVoiceMailTag; 1053 } 1054 if (isCphsMailboxEnabled()) { 1055 adn = new AdnRecord(mVoiceMailTag, mVoiceMailNum); 1056 Message onCphsCompleted = (Message) ar.userObj; 1057 1058 /* write to cphs mailbox whenever it is available but 1059 * we only need notify caller once if both updating are 1060 * successful. 1061 * 1062 * so if set_mbdn successful, notify caller here and set 1063 * onCphsCompleted to null 1064 */ 1065 if (ar.exception == null && ar.userObj != null) { 1066 AsyncResult.forMessage(((Message) ar.userObj)).exception = null; 1067 ((Message) ar.userObj).sendToTarget(); 1068 1069 if (DBG) log("Callback with MBDN successful."); 1070 1071 onCphsCompleted = null; 1072 } 1073 1074 new AdnRecordLoader(mFh) 1075 .updateEF(adn, EF_MAILBOX_CPHS, EF_EXT1, 1, null, 1076 obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE, 1077 AdnRecordLoader.VOICEMAIL_ALPHATAG_ARG, 1078 0 /* ignored arg2 */, onCphsCompleted)); 1079 } else { 1080 if (ar.userObj != null) { 1081 CarrierConfigManager configManager = (CarrierConfigManager) 1082 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1083 if (ar.exception != null && configManager != null) { 1084 PersistableBundle b = configManager.getConfigForSubId( 1085 SubscriptionManager.getSubscriptionId( 1086 mParentApp.getPhoneId())); 1087 if (b != null && b.getBoolean( 1088 CarrierConfigManager.KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL)) { 1089 // GsmCdmaPhone will store vm number on device 1090 // when IccVmNotSupportedException occurred 1091 AsyncResult.forMessage(((Message) ar.userObj)).exception = 1092 new IccVmNotSupportedException( 1093 "Update SIM voice mailbox error"); 1094 } else { 1095 AsyncResult.forMessage(((Message) ar.userObj)) 1096 .exception = ar.exception; 1097 } 1098 } else { 1099 AsyncResult.forMessage(((Message) ar.userObj)) 1100 .exception = ar.exception; 1101 } 1102 ((Message) ar.userObj).sendToTarget(); 1103 } 1104 } 1105 break; 1106 case EVENT_SET_CPHS_MAILBOX_DONE: 1107 isRecordLoadResponse = false; 1108 ar = (AsyncResult) msg.obj; 1109 if (ar.exception == null) { 1110 if (ar.result != null) { 1111 AdnRecord adnRecord = (AdnRecord) (ar.result); 1112 if (adnRecord != null) { 1113 mNewVoiceMailTag = adnRecord.mAlphaTag; 1114 } 1115 } 1116 mVoiceMailNum = mNewVoiceMailNum; 1117 mVoiceMailTag = mNewVoiceMailTag; 1118 } else { 1119 if (DBG) log("Set CPHS MailBox with exception: " + ar.exception); 1120 } 1121 if (ar.userObj != null) { 1122 if (DBG) log("Callback with CPHS MB successful."); 1123 AsyncResult.forMessage(((Message) ar.userObj)).exception 1124 = ar.exception; 1125 ((Message) ar.userObj).sendToTarget(); 1126 } 1127 break; 1128 case EVENT_GET_CFIS_DONE: 1129 isRecordLoadResponse = true; 1130 1131 ar = (AsyncResult) msg.obj; 1132 data = (byte[]) ar.result; 1133 1134 if (ar.exception != null) { 1135 mEfCfis = null; 1136 } else { 1137 log("EF_CFIS: " + IccUtils.bytesToHexString(data)); 1138 mEfCfis = data; 1139 } 1140 1141 break; 1142 1143 case EVENT_GET_CSP_CPHS_DONE: 1144 isRecordLoadResponse = true; 1145 1146 ar = (AsyncResult) msg.obj; 1147 1148 if (ar.exception != null) { 1149 loge("Exception in fetching EF_CSP data " + ar.exception); 1150 break; 1151 } 1152 1153 data = (byte[]) ar.result; 1154 1155 log("EF_CSP: " + IccUtils.bytesToHexString(data)); 1156 handleEfCspData(data); 1157 break; 1158 1159 case EVENT_GET_GID1_DONE: 1160 isRecordLoadResponse = true; 1161 1162 ar = (AsyncResult) msg.obj; 1163 data = (byte[]) ar.result; 1164 1165 if (ar.exception != null) { 1166 loge("Exception in get GID1 " + ar.exception); 1167 mGid1 = null; 1168 break; 1169 } 1170 1171 mGid1 = IccUtils.bytesToHexString(data); 1172 1173 log("GID1: " + mGid1); 1174 1175 break; 1176 1177 case EVENT_GET_GID2_DONE: 1178 isRecordLoadResponse = true; 1179 ar = (AsyncResult) msg.obj; 1180 data = (byte[]) ar.result; 1181 1182 if (ar.exception != null) { 1183 loge("Exception in get GID2 " + ar.exception); 1184 mGid2 = null; 1185 break; 1186 } 1187 1188 mGid2 = IccUtils.bytesToHexString(data); 1189 1190 log("GID2: " + mGid2); 1191 1192 break; 1193 1194 case EVENT_GET_PLMN_W_ACT_DONE: 1195 isRecordLoadResponse = true; 1196 ar = (AsyncResult) msg.obj; 1197 data = (byte[]) ar.result; 1198 1199 if (ar.exception != null || data == null) { 1200 loge("Failed getting User PLMN with Access Tech Records: " + ar.exception); 1201 break; 1202 } else { 1203 log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data)); 1204 mPlmnActRecords = PlmnActRecord.getRecords(data); 1205 if (VDBG) log("PlmnActRecords=" + Arrays.toString(mPlmnActRecords)); 1206 } 1207 break; 1208 1209 case EVENT_GET_OPLMN_W_ACT_DONE: 1210 isRecordLoadResponse = true; 1211 ar = (AsyncResult) msg.obj; 1212 data = (byte[]) ar.result; 1213 1214 if (ar.exception != null || data == null) { 1215 loge("Failed getting Operator PLMN with Access Tech Records: " 1216 + ar.exception); 1217 break; 1218 } else { 1219 log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data)); 1220 mOplmnActRecords = PlmnActRecord.getRecords(data); 1221 if (VDBG) log("OplmnActRecord[]=" + Arrays.toString(mOplmnActRecords)); 1222 } 1223 break; 1224 1225 case EVENT_GET_HPLMN_W_ACT_DONE: 1226 isRecordLoadResponse = true; 1227 ar = (AsyncResult) msg.obj; 1228 data = (byte[]) ar.result; 1229 1230 if (ar.exception != null || data == null) { 1231 loge("Failed getting Home PLMN with Access Tech Records: " + ar.exception); 1232 break; 1233 } else { 1234 log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data)); 1235 mHplmnActRecords = PlmnActRecord.getRecords(data); 1236 log("HplmnActRecord[]=" + Arrays.toString(mHplmnActRecords)); 1237 } 1238 break; 1239 1240 case EVENT_GET_EHPLMN_DONE: 1241 isRecordLoadResponse = true; 1242 ar = (AsyncResult) msg.obj; 1243 data = (byte[]) ar.result; 1244 if (ar.exception != null || data == null) { 1245 loge("Failed getting Equivalent Home PLMNs: " + ar.exception); 1246 break; 1247 } else { 1248 mEhplmns = parseBcdPlmnList(data, "Equivalent Home"); 1249 } 1250 break; 1251 1252 case EVENT_GET_FPLMN_DONE: 1253 isRecordLoadResponse = true; 1254 ar = (AsyncResult) msg.obj; 1255 data = (byte[]) ar.result; 1256 if (ar.exception != null || data == null) { 1257 loge("Failed getting Forbidden PLMNs: " + ar.exception); 1258 } else { 1259 mFplmns = parseBcdPlmnList(data, "Forbidden"); 1260 } 1261 if (msg.arg1 == HANDLER_ACTION_SEND_RESPONSE) { 1262 if (VDBG) logv("getForbiddenPlmns(): send async response"); 1263 isRecordLoadResponse = false; 1264 int key = msg.arg2; 1265 Message response = retrievePendingTransaction(key).first; 1266 if (response != null) { 1267 if (ar.exception == null && data != null && mFplmns != null) { 1268 AsyncResult.forMessage(response, Arrays.copyOf(mFplmns, 1269 mFplmns.length), null); 1270 } else { 1271 AsyncResult.forMessage(response, null, ar.exception); 1272 } 1273 response.sendToTarget(); 1274 } else { 1275 loge("Failed to retrieve a response message for FPLMN"); 1276 break; 1277 } 1278 } 1279 break; 1280 1281 case EVENT_GET_FPLMN_SIZE_DONE: 1282 ar = (AsyncResult) msg.obj; 1283 int key = msg.arg2; 1284 1285 Message response; 1286 Pair<Message, Object> transaction = null; 1287 if (ar.exception != null && ar.userObj != null) { 1288 response = (Message) ar.userObj; 1289 } else { 1290 transaction = retrievePendingTransaction(key); 1291 response = Objects.requireNonNull(transaction.first); 1292 } 1293 1294 if (ar.exception != null) { 1295 AsyncResult.forMessage(response).exception = ar.exception; 1296 response.sendToTarget(); 1297 break; 1298 } 1299 List<String> fplmns = (List<String>) transaction.second; 1300 int dataLength = (int) ar.result; 1301 if (dataLength < 0 || dataLength % FPLMN_BYTE_SIZE != 0) { 1302 loge("Failed to retrieve a correct fplmn size: " + dataLength); 1303 AsyncResult.forMessage(response, -1, null); 1304 response.sendToTarget(); 1305 break; 1306 } 1307 1308 int maxWritebaleFplmns = dataLength / FPLMN_BYTE_SIZE; 1309 List<String> fplmnsToWrite; 1310 if (fplmns.size() <= maxWritebaleFplmns) { 1311 fplmnsToWrite = fplmns; 1312 } else { 1313 fplmnsToWrite = fplmns.subList(0, maxWritebaleFplmns); 1314 } 1315 key = storePendingTransaction(response, fplmnsToWrite); 1316 byte[] encodededFplmns = IccUtils.encodeFplmns(fplmns, dataLength); 1317 mFh.updateEFTransparent( 1318 EF_FPLMN, 1319 encodededFplmns, 1320 obtainMessage( 1321 EVENT_SET_FPLMN_DONE, 1322 msg.arg1, 1323 key)); 1324 break; 1325 1326 case EVENT_SET_FPLMN_DONE: 1327 ar = (AsyncResult) msg.obj; 1328 if (ar.exception != null) { 1329 loge("Failed setting Forbidden PLMNs: " + ar.exception); 1330 } else { 1331 transaction = retrievePendingTransaction(msg.arg2); 1332 response = transaction.first; 1333 mFplmns = ((List<String>) transaction.second).toArray(new String[0]); 1334 if (msg.arg1 == HANDLER_ACTION_SEND_RESPONSE) { 1335 AsyncResult.forMessage(response, mFplmns.length, null); 1336 response.sendToTarget(); 1337 } 1338 log("Successfully setted fplmns " + ar.result); 1339 } 1340 break; 1341 1342 case EVENT_GET_PSISMSC_DONE: 1343 isRecordLoadResponse = true; 1344 ar = (AsyncResult) msg.obj; 1345 if (ar.exception != null) { 1346 loge("Failed to read USIM EF_PSISMSC field error=" + ar.exception); 1347 } else { 1348 data = (byte[]) ar.result; 1349 if (data != null && data.length > 0) { 1350 mPsiSmsc = parseEfPsiSmsc(data); 1351 if (VDBG) { 1352 log("SIMRecords - EF_PSISMSC value = " + mPsiSmsc); 1353 } 1354 } 1355 } 1356 break; 1357 1358 case EVENT_GET_SMSS_RECORD_DONE: 1359 isRecordLoadResponse = true; 1360 ar = (AsyncResult) msg.obj; 1361 if (ar.exception != null) { 1362 loge("Failed to read USIM EF_SMSS field error=" + ar.exception); 1363 } else { 1364 mSmssValues = (byte[]) ar.result; 1365 if (VDBG) { 1366 log("SIMRecords - EF_SMSS TPMR value = " + getSmssTpmrValue()); 1367 } 1368 } 1369 break; 1370 1371 default: 1372 super.handleMessage(msg); // IccRecords handles generic record load responses 1373 } 1374 } catch (RuntimeException exc) { 1375 // I don't want these exceptions to be fatal 1376 logw("Exception parsing SIM record", exc); 1377 } finally { 1378 // Count up record load responses even if they are fails 1379 if (isRecordLoadResponse) { 1380 onRecordLoaded(); 1381 } 1382 } 1383 } 1384 1385 private class EfPlLoaded implements IccRecordLoaded { getEfName()1386 public String getEfName() { 1387 return "EF_PL"; 1388 } 1389 onRecordLoaded(AsyncResult ar)1390 public void onRecordLoaded(AsyncResult ar) { 1391 mEfPl = (byte[]) ar.result; 1392 if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEfPl)); 1393 } 1394 } 1395 1396 private class EfUsimLiLoaded implements IccRecordLoaded { getEfName()1397 public String getEfName() { 1398 return "EF_LI"; 1399 } 1400 onRecordLoaded(AsyncResult ar)1401 public void onRecordLoaded(AsyncResult ar) { 1402 mEfLi = (byte[]) ar.result; 1403 if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEfLi)); 1404 } 1405 } 1406 1407 @Override handleFileUpdate(int efid)1408 protected void handleFileUpdate(int efid) { 1409 switch(efid) { 1410 case EF_MBDN: 1411 mRecordsToLoad++; 1412 new AdnRecordLoader(mFh).loadFromEF(EF_MBDN, EF_EXT6, 1413 mMailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE)); 1414 break; 1415 case EF_MAILBOX_CPHS: 1416 mRecordsToLoad++; 1417 new AdnRecordLoader(mFh).loadFromEF(EF_MAILBOX_CPHS, EF_EXT1, 1418 1, obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE)); 1419 break; 1420 case EF_CSP_CPHS: 1421 mRecordsToLoad++; 1422 log("[CSP] SIM Refresh for EF_CSP_CPHS"); 1423 mFh.loadEFTransparent(EF_CSP_CPHS, 1424 obtainMessage(EVENT_GET_CSP_CPHS_DONE)); 1425 break; 1426 case EF_FDN: 1427 if (DBG) log("SIM Refresh called for EF_FDN"); 1428 mParentApp.queryFdn(); 1429 mAdnCache.reset(); 1430 break; 1431 case EF_MSISDN: 1432 mRecordsToLoad++; 1433 log("SIM Refresh called for EF_MSISDN"); 1434 new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1, 1435 obtainMessage(EVENT_GET_MSISDN_DONE)); 1436 break; 1437 case EF_CFIS: 1438 case EF_CFF_CPHS: 1439 log("SIM Refresh called for EF_CFIS or EF_CFF_CPHS"); 1440 loadCallForwardingRecords(); 1441 break; 1442 default: 1443 // For now, fetch all records if this is not a 1444 // voicemail number. 1445 // TODO: Handle other cases, instead of fetching all. 1446 mLoaded.set(false); 1447 mAdnCache.reset(); 1448 fetchSimRecords(); 1449 break; 1450 } 1451 } 1452 1453 /** 1454 * Dispatch 3GPP format message to registrant ({@code GsmCdmaPhone}) to pass to the 3GPP SMS 1455 * dispatcher for delivery. 1456 */ dispatchGsmMessage(SmsMessage message)1457 private void dispatchGsmMessage(SmsMessage message) { 1458 mNewSmsRegistrants.notifyResult(message); 1459 } 1460 handleSms(byte[] ba)1461 private void handleSms(byte[] ba) { 1462 if (DBG) log("handleSms status : " + ba[0]); 1463 1464 // ba[0] is status byte. (see 3GPP TS 51.011 10.5.3) 1465 if ((ba[0] & 0x07) == STATUS_ON_ICC_UNREAD) { 1466 int n = ba.length; 1467 1468 // Note: Data may include trailing FF's. That's OK; message 1469 // should still parse correctly. 1470 byte[] pdu = new byte[n - 1]; 1471 System.arraycopy(ba, 1, pdu, 0, n - 1); 1472 SmsMessage message = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP); 1473 1474 dispatchGsmMessage(message); 1475 } 1476 } 1477 handleSmses(ArrayList<byte[]> messages)1478 private void handleSmses(ArrayList<byte[]> messages) { 1479 int count = messages.size(); 1480 1481 for (int i = 0; i < count; i++) { 1482 byte[] ba = messages.get(i); 1483 1484 if (DBG) log("handleSmses status " + i + ": " + ba[0]); 1485 1486 // ba[0] is status byte. (see 3GPP TS 51.011 10.5.3) 1487 if ((ba[0] & 0x07) == STATUS_ON_ICC_UNREAD) { 1488 int n = ba.length; 1489 1490 // Note: Data may include trailing FF's. That's OK; message 1491 // should still parse correctly. 1492 byte[] pdu = new byte[n - 1]; 1493 System.arraycopy(ba, 1, pdu, 0, n - 1); 1494 SmsMessage message = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP); 1495 1496 dispatchGsmMessage(message); 1497 1498 ba[0] = (byte) STATUS_ON_ICC_READ; 1499 1500 if (false) { // FIXME: writing seems to crash RdoServD 1501 mFh.updateEFLinearFixed(EF_SMS, 1502 i, ba, null, obtainMessage(EVENT_MARK_SMS_READ_DONE, i)); 1503 } 1504 } 1505 } 1506 } 1507 1508 @Override onRecordLoaded()1509 protected void onRecordLoaded() { 1510 // One record loaded successfully or failed, In either case 1511 // we need to update the recordsToLoad count 1512 mRecordsToLoad -= 1; 1513 if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested); 1514 1515 if (getRecordsLoaded()) { 1516 onAllRecordsLoaded(); 1517 } else if (getLockedRecordsLoaded() || getNetworkLockedRecordsLoaded()) { 1518 onLockedAllRecordsLoaded(); 1519 } else if (mRecordsToLoad < 0) { 1520 loge("recordsToLoad <0, programmer error suspected"); 1521 mRecordsToLoad = 0; 1522 } 1523 } 1524 setVoiceCallForwardingFlagFromSimRecords()1525 private void setVoiceCallForwardingFlagFromSimRecords() { 1526 if (validEfCfis(mEfCfis)) { 1527 // Refer TS 51.011 Section 10.3.46 for the content description 1528 mCallForwardingStatus = (mEfCfis[1] & 0x01); 1529 log("EF_CFIS: callForwardingEnabled=" + mCallForwardingStatus); 1530 } else if (mEfCff != null) { 1531 mCallForwardingStatus = 1532 ((mEfCff[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE) ? 1533 CALL_FORWARDING_STATUS_ENABLED : CALL_FORWARDING_STATUS_DISABLED; 1534 log("EF_CFF: callForwardingEnabled=" + mCallForwardingStatus); 1535 } else { 1536 mCallForwardingStatus = CALL_FORWARDING_STATUS_UNKNOWN; 1537 log("EF_CFIS and EF_CFF not valid. callForwardingEnabled=" + mCallForwardingStatus); 1538 } 1539 } 1540 setSimLanguageFromEF()1541 private void setSimLanguageFromEF() { 1542 Resources resource = Resources.getSystem(); 1543 if (resource.getBoolean(com.android.internal.R.bool.config_use_sim_language_file)) { 1544 setSimLanguage(mEfLi, mEfPl); 1545 } else { 1546 if (DBG) log ("Not using EF LI/EF PL"); 1547 } 1548 } 1549 onLockedAllRecordsLoaded()1550 private void onLockedAllRecordsLoaded() { 1551 setSimLanguageFromEF(); 1552 setVoiceCallForwardingFlagFromSimRecords(); 1553 if (mLockedRecordsReqReason == LOCKED_RECORDS_REQ_REASON_LOCKED) { 1554 mLockedRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); 1555 } else if (mLockedRecordsReqReason == LOCKED_RECORDS_REQ_REASON_NETWORK_LOCKED) { 1556 mNetworkLockedRecordsLoadedRegistrants.notifyRegistrants( 1557 new AsyncResult(null, null, null)); 1558 } else { 1559 loge("onLockedAllRecordsLoaded: unexpected mLockedRecordsReqReason " 1560 + mLockedRecordsReqReason); 1561 } 1562 } 1563 1564 @Override onAllRecordsLoaded()1565 protected void onAllRecordsLoaded() { 1566 if (DBG) log("record load complete"); 1567 1568 setSimLanguageFromEF(); 1569 setVoiceCallForwardingFlagFromSimRecords(); 1570 1571 // Some fields require more than one SIM record to set 1572 1573 String operator = getOperatorNumeric(); 1574 if (!TextUtils.isEmpty(operator)) { 1575 log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" + 1576 operator + "'"); 1577 mTelephonyManager.setSimOperatorNumericForPhone( 1578 mParentApp.getPhoneId(), operator); 1579 } else { 1580 log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping"); 1581 } 1582 1583 String imsi = getIMSI(); 1584 1585 if (!TextUtils.isEmpty(imsi) && imsi.length() >= 3) { 1586 log("onAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + imsi) : "")); 1587 mTelephonyManager.setSimCountryIsoForPhone( 1588 mParentApp.getPhoneId(), MccTable.countryCodeForMcc(imsi.substring(0, 3))); 1589 } else { 1590 log("onAllRecordsLoaded empty imsi skipping setting mcc"); 1591 } 1592 1593 setVoiceMailByCountry(operator); 1594 mLoaded.set(true); 1595 mRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); 1596 } 1597 1598 //***** Private methods 1599 setVoiceMailByCountry(String spn)1600 private void setVoiceMailByCountry (String spn) { 1601 if (mDestroyed.get()) { 1602 return; 1603 } 1604 if (mVmConfig.containsCarrier(spn)) { 1605 mIsVoiceMailFixed = true; 1606 mVoiceMailNum = mVmConfig.getVoiceMailNumber(spn); 1607 mVoiceMailTag = mVmConfig.getVoiceMailTag(spn); 1608 } 1609 } 1610 1611 /** 1612 * String[] of forbidden PLMNs will be sent to the Message's handler 1613 * in the result field of an AsyncResult in the response.obj. 1614 */ getForbiddenPlmns(Message response)1615 public void getForbiddenPlmns(Message response) { 1616 int key = storePendingTransaction(response); 1617 mFh.loadEFTransparent(EF_FPLMN, obtainMessage( 1618 EVENT_GET_FPLMN_DONE, HANDLER_ACTION_SEND_RESPONSE, key)); 1619 } 1620 1621 /** 1622 * Set the forbidden PLMNs on the sim 1623 * 1624 * @param response Response to be send back. 1625 * @param fplmns List of fplmns to be written to SIM. 1626 */ setForbiddenPlmns(Message response, List<String> fplmns)1627 public void setForbiddenPlmns(Message response, List<String> fplmns) { 1628 int key = storePendingTransaction(response, fplmns); 1629 mFh.getEFTransparentRecordSize( 1630 EF_FPLMN, 1631 obtainMessage(EVENT_GET_FPLMN_SIZE_DONE, HANDLER_ACTION_SEND_RESPONSE, key)); 1632 } 1633 1634 1635 @Override onReady()1636 public void onReady() { 1637 fetchSimRecords(); 1638 } 1639 1640 @Override onLocked()1641 protected void onLocked() { 1642 if (DBG) log("only fetch EF_LI, EF_PL and EF_ICCID in locked state"); 1643 super.onLocked(); 1644 1645 loadEfLiAndEfPl(); 1646 1647 mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); 1648 mRecordsToLoad++; 1649 } 1650 loadEfLiAndEfPl()1651 private void loadEfLiAndEfPl() { 1652 if (mParentApp.getType() == AppType.APPTYPE_USIM) { 1653 mFh.loadEFTransparent(EF_LI, 1654 obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfUsimLiLoaded())); 1655 mRecordsToLoad++; 1656 1657 mFh.loadEFTransparent(EF_PL, 1658 obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded())); 1659 mRecordsToLoad++; 1660 } 1661 } 1662 loadCallForwardingRecords()1663 private void loadCallForwardingRecords() { 1664 mRecordsRequested = true; 1665 mFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE)); 1666 mRecordsToLoad++; 1667 mFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE)); 1668 mRecordsToLoad++; 1669 } 1670 1671 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) fetchSimRecords()1672 protected void fetchSimRecords() { 1673 mRecordsRequested = true; 1674 1675 if (DBG) log("fetchSimRecords " + mRecordsToLoad); 1676 1677 mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE)); 1678 mRecordsToLoad++; 1679 1680 mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); 1681 mRecordsToLoad++; 1682 1683 // FIXME should examine EF[MSISDN]'s capability configuration 1684 // to determine which is the voice/data/fax line 1685 new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1, 1686 obtainMessage(EVENT_GET_MSISDN_DONE)); 1687 mRecordsToLoad++; 1688 1689 // Record number is subscriber profile 1690 mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE)); 1691 mRecordsToLoad++; 1692 1693 mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE)); 1694 mRecordsToLoad++; 1695 1696 // Record number is subscriber profile 1697 mFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE)); 1698 mRecordsToLoad++; 1699 1700 1701 // Also load CPHS-style voice mail indicator, which stores 1702 // the same info as EF[MWIS]. If both exist, both are updated 1703 // but the EF[MWIS] data is preferred 1704 // Please note this must be loaded after EF[MWIS] 1705 mFh.loadEFTransparent( 1706 EF_VOICE_MAIL_INDICATOR_CPHS, 1707 obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE)); 1708 mRecordsToLoad++; 1709 1710 // Same goes for Call Forward Status indicator: fetch both 1711 // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred. 1712 loadCallForwardingRecords(); 1713 1714 getSpnFsm(true, null); 1715 1716 mFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE)); 1717 mRecordsToLoad++; 1718 1719 mFh.loadEFLinearFixedAll(EF_PNN, obtainMessage(EVENT_GET_PNN_DONE)); 1720 mRecordsToLoad++; 1721 1722 mFh.loadEFLinearFixedAll(EF_OPL, obtainMessage(EVENT_GET_OPL_DONE)); 1723 mRecordsToLoad++; 1724 1725 mFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE)); 1726 mRecordsToLoad++; 1727 1728 mFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE)); 1729 mRecordsToLoad++; 1730 1731 mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE)); 1732 mRecordsToLoad++; 1733 1734 mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE)); 1735 mRecordsToLoad++; 1736 1737 mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE)); 1738 mRecordsToLoad++; 1739 1740 mFh.loadEFTransparent(EF_PLMN_W_ACT, obtainMessage(EVENT_GET_PLMN_W_ACT_DONE)); 1741 mRecordsToLoad++; 1742 1743 mFh.loadEFTransparent(EF_OPLMN_W_ACT, obtainMessage(EVENT_GET_OPLMN_W_ACT_DONE)); 1744 mRecordsToLoad++; 1745 1746 mFh.loadEFTransparent(EF_HPLMN_W_ACT, obtainMessage(EVENT_GET_HPLMN_W_ACT_DONE)); 1747 mRecordsToLoad++; 1748 1749 mFh.loadEFTransparent(EF_EHPLMN, obtainMessage(EVENT_GET_EHPLMN_DONE)); 1750 mRecordsToLoad++; 1751 1752 mFh.loadEFTransparent(EF_FPLMN, obtainMessage( 1753 EVENT_GET_FPLMN_DONE, HANDLER_ACTION_NONE, -1)); 1754 mRecordsToLoad++; 1755 1756 loadEfLiAndEfPl(); 1757 mFh.getEFLinearRecordSize(EF_SMS, obtainMessage(EVENT_GET_SMS_RECORD_SIZE_DONE)); 1758 mRecordsToLoad++; 1759 1760 mFh.loadEFLinearFixed(EF_PSISMSC, 1, obtainMessage(EVENT_GET_PSISMSC_DONE)); 1761 mRecordsToLoad++; 1762 1763 // XXX should seek instead of examining them all 1764 if (false) { // XXX 1765 mFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE)); 1766 mRecordsToLoad++; 1767 } 1768 1769 mFh.loadEFTransparent(EF_SMSS, obtainMessage(EVENT_GET_SMSS_RECORD_DONE)); 1770 mRecordsToLoad++; 1771 1772 if (CRASH_RIL) { 1773 String sms = "0107912160130310f20404d0110041007030208054832b0120" 1774 + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 1775 + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 1776 + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 1777 + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 1778 + "ffffffffffffffffffffffffffffff"; 1779 byte[] ba = IccUtils.hexStringToBytes(sms); 1780 1781 mFh.updateEFLinearFixed(EF_SMS, 1, ba, null, 1782 obtainMessage(EVENT_MARK_SMS_READ_DONE, 1)); 1783 } 1784 if (DBG) log("fetchSimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested); 1785 } 1786 1787 @Override 1788 @CarrierNameDisplayConditionBitmask getCarrierNameDisplayCondition()1789 public int getCarrierNameDisplayCondition() { 1790 return mCarrierNameDisplayCondition; 1791 } 1792 1793 /** 1794 * States of Get SPN Finite State Machine which only used by getSpnFsm() 1795 */ 1796 @UnsupportedAppUsage(implicitMember = 1797 "values()[Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;") 1798 private enum GetSpnFsmState { 1799 IDLE, // No initialized 1800 @UnsupportedAppUsage 1801 INIT, // Start FSM 1802 @UnsupportedAppUsage 1803 READ_SPN_3GPP, // Load EF_SPN firstly 1804 @UnsupportedAppUsage 1805 READ_SPN_CPHS, // Load EF_SPN_CPHS secondly 1806 @UnsupportedAppUsage 1807 READ_SPN_SHORT_CPHS // Load EF_SPN_SHORT_CPHS last 1808 } 1809 1810 /** 1811 * Finite State Machine to load Service Provider Name , which can be stored 1812 * in either EF_SPN (3GPP), EF_SPN_CPHS, or EF_SPN_SHORT_CPHS (CPHS4.2) 1813 * 1814 * After starting, FSM will search SPN EFs in order and stop after finding 1815 * the first valid SPN 1816 * 1817 * If the FSM gets restart while waiting for one of 1818 * SPN EFs results (i.e. a SIM refresh occurs after issuing 1819 * read EF_CPHS_SPN), it will re-initialize only after 1820 * receiving and discarding the unfinished SPN EF result. 1821 * 1822 * @param start set true only for initialize loading 1823 * @param ar the AsyncResult from loadEFTransparent 1824 * ar.exception holds exception in error 1825 * ar.result is byte[] for data in success 1826 */ 1827 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getSpnFsm(boolean start, AsyncResult ar)1828 private void getSpnFsm(boolean start, AsyncResult ar) { 1829 byte[] data; 1830 1831 if (start) { 1832 // Check previous state to see if there is outstanding 1833 // SPN read 1834 if (mSpnState == GetSpnFsmState.READ_SPN_3GPP 1835 || mSpnState == GetSpnFsmState.READ_SPN_CPHS 1836 || mSpnState == GetSpnFsmState.READ_SPN_SHORT_CPHS 1837 || mSpnState == GetSpnFsmState.INIT) { 1838 // Set INIT then return so the INIT code 1839 // will run when the outstanding read done. 1840 mSpnState = GetSpnFsmState.INIT; 1841 return; 1842 } else { 1843 mSpnState = GetSpnFsmState.INIT; 1844 } 1845 } 1846 1847 switch(mSpnState){ 1848 case INIT: 1849 setServiceProviderName(null); 1850 1851 mFh.loadEFTransparent(EF_SPN, 1852 obtainMessage(EVENT_GET_SPN_DONE)); 1853 mRecordsToLoad++; 1854 1855 mSpnState = GetSpnFsmState.READ_SPN_3GPP; 1856 break; 1857 case READ_SPN_3GPP: 1858 if (ar != null && ar.exception == null) { 1859 data = (byte[]) ar.result; 1860 1861 // Reference: 3GPP TS 31.102 section 4.2.12 EF_SPN 1862 // The first byte is display condition. 1863 mCarrierNameDisplayCondition = 1864 convertSpnDisplayConditionToBitmask(data[0] & 0xff); 1865 1866 setServiceProviderName(IccUtils.adnStringFieldToString( 1867 data, 1, data.length - 1)); 1868 // for card double-check and brand override 1869 // we have to do this: 1870 final String spn = getServiceProviderName(); 1871 1872 if (spn == null || spn.length() == 0) { 1873 mSpnState = GetSpnFsmState.READ_SPN_CPHS; 1874 } else { 1875 if (DBG) log("Load EF_SPN: " + spn 1876 + " carrierNameDisplayCondition: " + mCarrierNameDisplayCondition); 1877 mTelephonyManager.setSimOperatorNameForPhone( 1878 mParentApp.getPhoneId(), spn); 1879 1880 mSpnState = GetSpnFsmState.IDLE; 1881 } 1882 } else { 1883 mSpnState = GetSpnFsmState.READ_SPN_CPHS; 1884 } 1885 1886 if (mSpnState == GetSpnFsmState.READ_SPN_CPHS) { 1887 mFh.loadEFTransparent( EF_SPN_CPHS, 1888 obtainMessage(EVENT_GET_SPN_DONE)); 1889 mRecordsToLoad++; 1890 1891 mCarrierNameDisplayCondition = DEFAULT_CARRIER_NAME_DISPLAY_CONDITION; 1892 } 1893 break; 1894 case READ_SPN_CPHS: 1895 if (ar != null && ar.exception == null) { 1896 data = (byte[]) ar.result; 1897 1898 setServiceProviderName(IccUtils.adnStringFieldToString( 1899 data, 0, data.length)); 1900 // for card double-check and brand override 1901 // we have to do this: 1902 final String spn = getServiceProviderName(); 1903 1904 if (spn == null || spn.length() == 0) { 1905 mSpnState = GetSpnFsmState.READ_SPN_SHORT_CPHS; 1906 } else { 1907 // Display CPHS Operator Name only when not roaming 1908 mCarrierNameDisplayCondition = 0; 1909 1910 if (DBG) log("Load EF_SPN_CPHS: " + spn); 1911 mTelephonyManager.setSimOperatorNameForPhone( 1912 mParentApp.getPhoneId(), spn); 1913 1914 mSpnState = GetSpnFsmState.IDLE; 1915 } 1916 } else { 1917 mSpnState = GetSpnFsmState.READ_SPN_SHORT_CPHS; 1918 } 1919 1920 if (mSpnState == GetSpnFsmState.READ_SPN_SHORT_CPHS) { 1921 mFh.loadEFTransparent( 1922 EF_SPN_SHORT_CPHS, obtainMessage(EVENT_GET_SPN_DONE)); 1923 mRecordsToLoad++; 1924 } 1925 break; 1926 case READ_SPN_SHORT_CPHS: 1927 if (ar != null && ar.exception == null) { 1928 data = (byte[]) ar.result; 1929 1930 setServiceProviderName(IccUtils.adnStringFieldToString( 1931 data, 0, data.length)); 1932 // for card double-check and brand override 1933 // we have to do this: 1934 final String spn = getServiceProviderName(); 1935 1936 if (spn == null || spn.length() == 0) { 1937 if (DBG) log("No SPN loaded in either CHPS or 3GPP"); 1938 } else { 1939 // Display CPHS Operator Name only when not roaming 1940 mCarrierNameDisplayCondition = 0; 1941 1942 if (DBG) log("Load EF_SPN_SHORT_CPHS: " + spn); 1943 mTelephonyManager.setSimOperatorNameForPhone( 1944 mParentApp.getPhoneId(), spn); 1945 } 1946 } else { 1947 setServiceProviderName(null); 1948 if (DBG) log("No SPN loaded in either CHPS or 3GPP"); 1949 } 1950 1951 mSpnState = GetSpnFsmState.IDLE; 1952 break; 1953 default: 1954 mSpnState = GetSpnFsmState.IDLE; 1955 } 1956 } 1957 1958 /** 1959 * Parse TS 51.011 EF[SPDI] record 1960 * This record contains the list of numeric network IDs that 1961 * are treated specially when determining SPN display 1962 */ parseEfSpdi(byte[] data)1963 private void parseEfSpdi(byte[] data) { 1964 SimTlv tlv = new SimTlv(data, 0, data.length); 1965 1966 byte[] plmnEntries = null; 1967 1968 for ( ; tlv.isValidObject() ; tlv.nextObject()) { 1969 // Skip SPDI tag, if existant 1970 if (tlv.getTag() == TAG_SPDI) { 1971 tlv = new SimTlv(tlv.getData(), 0, tlv.getData().length); 1972 } 1973 // There should only be one TAG_SPDI_PLMN_LIST 1974 if (tlv.getTag() == TAG_SPDI_PLMN_LIST) { 1975 plmnEntries = tlv.getData(); 1976 break; 1977 } 1978 } 1979 1980 if (plmnEntries == null) { 1981 return; 1982 } 1983 1984 List<String> tmpSpdi = new ArrayList<>(plmnEntries.length / 3); 1985 for (int i = 0; i + 2 < plmnEntries.length; i += 3) { 1986 String plmnCode = IccUtils.bcdPlmnToString(plmnEntries, i); 1987 if (!TextUtils.isEmpty(plmnCode)) { 1988 tmpSpdi.add(plmnCode); 1989 } 1990 } 1991 log("parseEfSpdi: " + tmpSpdi); 1992 1993 mSpdi = tmpSpdi.toArray(new String[tmpSpdi.size()]); 1994 } 1995 1996 /** 1997 * Parse EF PLMN Network Name (PNN) record from SIM 1998 * Reference: 3GPP TS 31.102 Section 4.2.58. 1999 */ parseEfPnn(ArrayList<byte[]> dataArray)2000 private void parseEfPnn(ArrayList<byte[]> dataArray) { 2001 if (dataArray == null) return; 2002 2003 final int count = dataArray.size(); 2004 List<PlmnNetworkName> tmpPnns = new ArrayList<>(count); 2005 for (int i = 0; i < count; i++) { 2006 byte[] data = dataArray.get(i); 2007 SimTlv tlv = new SimTlv(data, 0, data.length); 2008 2009 String longName = null; 2010 String shortName = null; 2011 for (; tlv.isValidObject(); tlv.nextObject()) { 2012 switch (tlv.getTag()) { 2013 case TAG_FULL_NETWORK_NAME: 2014 longName = IccUtils.networkNameToString(tlv.getData(), 0, 2015 tlv.getData().length); 2016 break; 2017 2018 case TAG_SHORT_NETWORK_NAME: 2019 shortName = IccUtils.networkNameToString(tlv.getData(), 0, 2020 tlv.getData().length); 2021 break; 2022 2023 case TAG_PLMN_ADDITIONAL_INFORMATION: 2024 // TODO(b/154300344): read PLMN Additional Information. 2025 break; 2026 } 2027 } 2028 // PNNs must maintain their original indices. They will be referred to by index in OPL. 2029 tmpPnns.add(new PlmnNetworkName(longName, shortName)); 2030 } 2031 log("parseEfPnn: " + tmpPnns); 2032 2033 mPnns = tmpPnns.toArray(new PlmnNetworkName[0]); 2034 2035 // For compatiblility with legacy code. 2036 if (mPnns.length > 0) mPnnHomeName = mPnns[0].getName(); 2037 } 2038 2039 /** 2040 * Parse EF Operator PLMN List (OPL) record from SIM 2041 * Reference: 3GPP TS 31.102 Section 4.2.59. 2042 */ parseEfOpl(ArrayList<byte[]> dataArray)2043 private void parseEfOpl(ArrayList<byte[]> dataArray) { 2044 if (dataArray == null) return; 2045 2046 final int count = dataArray.size(); 2047 List<OperatorPlmnInfo> tmpOpl = new ArrayList<>(count); 2048 for (int i = 0; i < count; i++) { 2049 byte[] data = dataArray.get(i); 2050 // data.length is 8 as defined in 3GPP TS 31.102 Section 4.2.59. 2051 // Byte 0 to 2 are for PLMN. 2052 // Byte 3 and 4 are for lacTacStart. 2053 // Byte 5 and 6 are for lacTacEnd. 2054 // Byte 7 is for PNN Record Identifier. 2055 if (data.length != 8) { 2056 loge("Invalid length for OPL record " + IccUtils.bytesToHexString(data)); 2057 continue; 2058 } 2059 2060 // A BCD value of 'D' in any of the MCC and/or MNC digits shall be used to indicate 2061 // a "wild" value for that corresponding MCC/MNC digit. 2062 String plmn = IccUtils.bcdPlmnToString(data, 0); 2063 if (plmn.length() < PLMN_MIN_LENGTH) { 2064 loge("Invalid length for decoded PLMN " + plmn); 2065 continue; 2066 } 2067 int lacTacStart = IccUtils.bytesToInt(data, 3, 2); 2068 int lacTacEnd = IccUtils.bytesToInt(data, 5, 2); 2069 int pnnRecordId = IccUtils.bytesToInt(data, 7, 1); 2070 2071 tmpOpl.add(new OperatorPlmnInfo(plmn, lacTacStart, lacTacEnd, pnnRecordId)); 2072 } 2073 log("parseEfOpl: " + tmpOpl); 2074 mOpl = tmpOpl.toArray(new OperatorPlmnInfo[0]); 2075 } 2076 2077 /** 2078 * convert a byte array of packed plmns to an array of strings 2079 */ parseBcdPlmnList(byte[] data, String description)2080 private String[] parseBcdPlmnList(byte[] data, String description) { 2081 final int packedBcdPlmnLenBytes = 3; 2082 log("Received " + description + " PLMNs, raw=" + IccUtils.bytesToHexString(data)); 2083 if (data.length == 0 || (data.length % packedBcdPlmnLenBytes) != 0) { 2084 loge("Received invalid " + description + " PLMN list"); 2085 return null; 2086 } 2087 int numPlmns = data.length / packedBcdPlmnLenBytes; 2088 int numValidPlmns = 0; 2089 String[] parsed = new String[numPlmns]; 2090 for (int i = 0; i < numPlmns; i++) { 2091 parsed[numValidPlmns] = IccUtils.bcdPlmnToString(data, i * packedBcdPlmnLenBytes); 2092 // we count the valid (non empty) records and only increment if valid 2093 if (!TextUtils.isEmpty(parsed[numValidPlmns])) numValidPlmns++; 2094 } 2095 String[] ret = Arrays.copyOf(parsed, numValidPlmns); 2096 if (VDBG) logv(description + " PLMNs: " + Arrays.toString(ret)); 2097 return ret; 2098 } 2099 2100 /** 2101 * check to see if Mailbox Number is allocated and activated in CPHS SST 2102 */ 2103 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isCphsMailboxEnabled()2104 private boolean isCphsMailboxEnabled() { 2105 if (mCphsInfo == null) return false; 2106 return ((mCphsInfo[1] & CPHS_SST_MBN_MASK) == CPHS_SST_MBN_ENABLED ); 2107 } 2108 2109 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2110 @Override log(String s)2111 protected void log(String s) { 2112 if (mParentApp != null) { 2113 Rlog.d(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s); 2114 } else { 2115 Rlog.d(LOG_TAG, "[SIMRecords] " + s); 2116 } 2117 } 2118 2119 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2120 @Override loge(String s)2121 protected void loge(String s) { 2122 if (mParentApp != null) { 2123 Rlog.e(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s); 2124 } else { 2125 Rlog.e(LOG_TAG, "[SIMRecords] " + s); 2126 } 2127 } 2128 logw(String s, Throwable tr)2129 protected void logw(String s, Throwable tr) { 2130 if (mParentApp != null) { 2131 Rlog.w(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s, tr); 2132 } else { 2133 Rlog.w(LOG_TAG, "[SIMRecords] " + s, tr); 2134 } 2135 } 2136 2137 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) logv(String s)2138 protected void logv(String s) { 2139 if (mParentApp != null) { 2140 Rlog.v(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s); 2141 } else { 2142 Rlog.v(LOG_TAG, "[SIMRecords] " + s); 2143 } 2144 } 2145 2146 /** 2147 * Return true if "Restriction of menu options for manual PLMN selection" 2148 * bit is set or EF_CSP data is unavailable, return false otherwise. 2149 */ 2150 @Override isCspPlmnEnabled()2151 public boolean isCspPlmnEnabled() { 2152 return mCspPlmnEnabled; 2153 } 2154 2155 /** 2156 * Parse EF_CSP data and check if 2157 * "Restriction of menu options for manual PLMN selection" is 2158 * Enabled/Disabled 2159 * 2160 * @param data EF_CSP hex data. 2161 */ handleEfCspData(byte[] data)2162 private void handleEfCspData(byte[] data) { 2163 // As per spec CPHS4_2.WW6, CPHS B.4.7.1, EF_CSP contains CPHS defined 2164 // 18 bytes (i.e 9 service groups info) and additional data specific to 2165 // operator. The valueAddedServicesGroup is not part of standard 2166 // services. This is operator specific and can be programmed any where. 2167 // Normally this is programmed as 10th service after the standard 2168 // services. 2169 int usedCspGroups = data.length / 2; 2170 // This is the "Service Group Number" of "Value Added Services Group". 2171 byte valueAddedServicesGroup = (byte)0xC0; 2172 2173 mCspPlmnEnabled = true; 2174 for (int i = 0; i < usedCspGroups; i++) { 2175 if (data[2 * i] == valueAddedServicesGroup) { 2176 log("[CSP] found ValueAddedServicesGroup, value " + data[(2 * i) + 1]); 2177 if ((data[(2 * i) + 1] & 0x80) == 0x80) { 2178 // Bit 8 is for 2179 // "Restriction of menu options for manual PLMN selection". 2180 // Operator Selection menu should be enabled. 2181 mCspPlmnEnabled = true; 2182 } else { 2183 mCspPlmnEnabled = false; 2184 // Operator Selection menu should be disabled. 2185 // Operator Selection Mode should be set to Automatic. 2186 log("[CSP] Set Automatic Network Selection"); 2187 mNetworkSelectionModeAutomaticRegistrants.notifyRegistrants(); 2188 } 2189 return; 2190 } 2191 } 2192 2193 log("[CSP] Value Added Service Group (0xC0), not found!"); 2194 } 2195 2196 @VisibleForTesting setMailboxIndex(int mailboxIndex)2197 public void setMailboxIndex(int mailboxIndex) { 2198 mMailboxIndex = mailboxIndex; 2199 } 2200 2201 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2202 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2203 pw.println("SIMRecords: " + this); 2204 pw.println(" extends:"); 2205 super.dump(fd, pw, args); 2206 pw.println(" mVmConfig=" + mVmConfig); 2207 pw.println(" mCallForwardingStatus=" + mCallForwardingStatus); 2208 pw.println(" mSpnState=" + mSpnState); 2209 pw.println(" mCphsInfo=" + IccUtils.bytesToHexString(mCphsInfo)); 2210 pw.println(" mCspPlmnEnabled=" + mCspPlmnEnabled); 2211 pw.println(" mEfMWIS[]=" + Arrays.toString(mEfMWIS)); 2212 pw.println(" mEfCPHS_MWI[]=" + Arrays.toString(mEfCPHS_MWI)); 2213 pw.println(" mEfCff[]=" + Arrays.toString(mEfCff)); 2214 pw.println(" mEfCfis[]=" + Arrays.toString(mEfCfis)); 2215 pw.println(" mCarrierNameDisplayCondition=" + mCarrierNameDisplayCondition); 2216 pw.println(" mSpdi[]=" + Arrays.toString(mSpdi)); 2217 pw.println(" mUsimServiceTable=" + mUsimServiceTable); 2218 pw.println(" mGid1=" + mGid1); 2219 if (mCarrierTestOverride.isInTestMode()) { 2220 pw.println(" mFakeGid1=" + mCarrierTestOverride.getFakeGid1()); 2221 } 2222 pw.println(" mGid2=" + mGid2); 2223 if (mCarrierTestOverride.isInTestMode()) { 2224 pw.println(" mFakeGid2=" + mCarrierTestOverride.getFakeGid2()); 2225 } 2226 pw.println(" mPnnHomeName=" + mPnnHomeName); 2227 if (mCarrierTestOverride.isInTestMode()) { 2228 pw.println(" mFakePnnHomeName=" + mCarrierTestOverride.getFakePnnHomeName()); 2229 } 2230 pw.println(" mPlmnActRecords[]=" + Arrays.toString(mPlmnActRecords)); 2231 pw.println(" mOplmnActRecords[]=" + Arrays.toString(mOplmnActRecords)); 2232 pw.println(" mHplmnActRecords[]=" + Arrays.toString(mHplmnActRecords)); 2233 pw.println(" mFplmns[]=" + Arrays.toString(mFplmns)); 2234 pw.println(" mEhplmns[]=" + Arrays.toString(mEhplmns)); 2235 pw.println(" mPsismsc=" + mPsiSmsc); 2236 pw.println(" TPMR=" + getSmssTpmrValue()); 2237 pw.flush(); 2238 } 2239 } 2240