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