SIMRecords.java revision c9a55d1e545ab7bc92e14c2ca1123ac71b18f7fe
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 17package com.android.internal.telephony.uicc; 18 19import android.content.Context; 20import android.os.AsyncResult; 21import android.os.Message; 22import android.os.SystemProperties; 23import android.telephony.TelephonyManager; 24import android.telephony.PhoneNumberUtils; 25import android.telephony.SmsMessage; 26import android.text.TextUtils; 27import android.telephony.Rlog; 28import android.content.res.Resources; 29 30import com.android.internal.telephony.CommandsInterface; 31import com.android.internal.telephony.MccTable; 32import com.android.internal.telephony.SmsConstants; 33import com.android.internal.telephony.SubscriptionController; 34import com.android.internal.telephony.gsm.SimTlv; 35import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 36import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType; 37 38import java.io.FileDescriptor; 39import java.io.PrintWriter; 40import java.util.ArrayList; 41import java.util.Arrays; 42 43/** 44 * {@hide} 45 */ 46public class SIMRecords extends IccRecords { 47 protected static final String LOG_TAG = "SIMRecords"; 48 49 private static final boolean CRASH_RIL = false; 50 51 // ***** Instance Variables 52 53 VoiceMailConstants mVmConfig; 54 55 56 SpnOverride mSpnOverride; 57 58 // ***** Cached SIM State; cleared on channel close 59 60 private boolean mCallForwardingEnabled; 61 62 63 /** 64 * States only used by getSpnFsm FSM 65 */ 66 private GetSpnFsmState mSpnState; 67 68 /** CPHS service information (See CPHS 4.2 B.3.1.1) 69 * It will be set in onSimReady if reading GET_CPHS_INFO successfully 70 * mCphsInfo[0] is CPHS Phase 71 * mCphsInfo[1] and mCphsInfo[2] is CPHS Service Table 72 */ 73 private byte[] mCphsInfo = null; 74 boolean mCspPlmnEnabled = true; 75 76 byte[] mEfMWIS = null; 77 byte[] mEfCPHS_MWI =null; 78 byte[] mEfCff = null; 79 byte[] mEfCfis = null; 80 81 byte[] mEfLi = null; 82 byte[] mEfPl = null; 83 84 int mSpnDisplayCondition; 85 // Numeric network codes listed in TS 51.011 EF[SPDI] 86 ArrayList<String> mSpdiNetworks = null; 87 88 String mPnnHomeName = null; 89 90 UsimServiceTable mUsimServiceTable; 91 92 @Override 93 public String toString() { 94 return "SimRecords: " + super.toString() 95 + " mVmConfig" + mVmConfig 96 + " mSpnOverride=" + "mSpnOverride" 97 + " callForwardingEnabled=" + mCallForwardingEnabled 98 + " spnState=" + mSpnState 99 + " mCphsInfo=" + mCphsInfo 100 + " mCspPlmnEnabled=" + mCspPlmnEnabled 101 + " efMWIS=" + mEfMWIS 102 + " efCPHS_MWI=" + mEfCPHS_MWI 103 + " mEfCff=" + mEfCff 104 + " mEfCfis=" + mEfCfis 105 + " getOperatorNumeric=" + getOperatorNumeric(); 106 } 107 108 // ***** Constants 109 110 // From TS 51.011 EF[SPDI] section 111 static final int TAG_SPDI = 0xA3; 112 static final int TAG_SPDI_PLMN_LIST = 0x80; 113 114 // Full Name IEI from TS 24.008 115 static final int TAG_FULL_NETWORK_NAME = 0x43; 116 117 // Short Name IEI from TS 24.008 118 static final int TAG_SHORT_NETWORK_NAME = 0x45; 119 120 // active CFF from CPHS 4.2 B.4.5 121 static final int CFF_UNCONDITIONAL_ACTIVE = 0x0a; 122 static final int CFF_UNCONDITIONAL_DEACTIVE = 0x05; 123 static final int CFF_LINE1_MASK = 0x0f; 124 static final int CFF_LINE1_RESET = 0xf0; 125 126 // CPHS Service Table (See CPHS 4.2 B.3.1) 127 private static final int CPHS_SST_MBN_MASK = 0x30; 128 private static final int CPHS_SST_MBN_ENABLED = 0x30; 129 130 // EF_CFIS related constants 131 // Spec reference TS 51.011 section 10.3.46. 132 private static final int CFIS_BCD_NUMBER_LENGTH_OFFSET = 2; 133 private static final int CFIS_TON_NPI_OFFSET = 3; 134 private static final int CFIS_ADN_CAPABILITY_ID_OFFSET = 14; 135 private static final int CFIS_ADN_EXTENSION_ID_OFFSET = 15; 136 137 // ***** Event Constants 138 private static final int EVENT_GET_IMSI_DONE = 3; 139 private static final int EVENT_GET_ICCID_DONE = 4; 140 private static final int EVENT_GET_MBI_DONE = 5; 141 private static final int EVENT_GET_MBDN_DONE = 6; 142 private static final int EVENT_GET_MWIS_DONE = 7; 143 private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8; 144 protected static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM 145 protected static final int EVENT_GET_MSISDN_DONE = 10; 146 private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11; 147 private static final int EVENT_GET_SPN_DONE = 12; 148 private static final int EVENT_GET_SPDI_DONE = 13; 149 private static final int EVENT_UPDATE_DONE = 14; 150 private static final int EVENT_GET_PNN_DONE = 15; 151 protected static final int EVENT_GET_SST_DONE = 17; 152 private static final int EVENT_GET_ALL_SMS_DONE = 18; 153 private static final int EVENT_MARK_SMS_READ_DONE = 19; 154 private static final int EVENT_SET_MBDN_DONE = 20; 155 private static final int EVENT_SMS_ON_SIM = 21; 156 private static final int EVENT_GET_SMS_DONE = 22; 157 private static final int EVENT_GET_CFF_DONE = 24; 158 private static final int EVENT_SET_CPHS_MAILBOX_DONE = 25; 159 private static final int EVENT_GET_INFO_CPHS_DONE = 26; 160 // private static final int EVENT_SET_MSISDN_DONE = 30; Defined in IccRecords as 30 161 private static final int EVENT_SIM_REFRESH = 31; 162 private static final int EVENT_GET_CFIS_DONE = 32; 163 private static final int EVENT_GET_CSP_CPHS_DONE = 33; 164 private static final int EVENT_GET_GID1_DONE = 34; 165 private static final int EVENT_APP_LOCKED = 35; 166 private static final int EVENT_GET_GID2_DONE = 36; 167 168 // Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length. 169 170 private static final String[] MCCMNC_CODES_HAVING_3DIGITS_MNC = { 171 "302370", "302720", "310260", 172 "405025", "405026", "405027", "405028", "405029", "405030", "405031", "405032", 173 "405033", "405034", "405035", "405036", "405037", "405038", "405039", "405040", 174 "405041", "405042", "405043", "405044", "405045", "405046", "405047", "405750", 175 "405751", "405752", "405753", "405754", "405755", "405756", "405799", "405800", 176 "405801", "405802", "405803", "405804", "405805", "405806", "405807", "405808", 177 "405809", "405810", "405811", "405812", "405813", "405814", "405815", "405816", 178 "405817", "405818", "405819", "405820", "405821", "405822", "405823", "405824", 179 "405825", "405826", "405827", "405828", "405829", "405830", "405831", "405832", 180 "405833", "405834", "405835", "405836", "405837", "405838", "405839", "405840", 181 "405841", "405842", "405843", "405844", "405845", "405846", "405847", "405848", 182 "405849", "405850", "405851", "405852", "405853", "405875", "405876", "405877", 183 "405878", "405879", "405880", "405881", "405882", "405883", "405884", "405885", 184 "405886", "405908", "405909", "405910", "405911", "405912", "405913", "405914", 185 "405915", "405916", "405917", "405918", "405919", "405920", "405921", "405922", 186 "405923", "405924", "405925", "405926", "405927", "405928", "405929", "405930", 187 "405931", "405932", "502142", "502143", "502145", "502146", "502147", "502148" 188 }; 189 190 // ***** Constructor 191 192 public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) { 193 super(app, c, ci); 194 195 mAdnCache = new AdnRecordCache(mFh); 196 197 mVmConfig = new VoiceMailConstants(); 198 mSpnOverride = new SpnOverride(); 199 200 mRecordsRequested = false; // No load request is made till SIM ready 201 202 // recordsToLoad is set to 0 because no requests are made yet 203 mRecordsToLoad = 0; 204 205 mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null); 206 mCi.registerForIccRefresh(this, EVENT_SIM_REFRESH, null); 207 208 // Start off by setting empty state 209 resetRecords(); 210 mParentApp.registerForReady(this, EVENT_APP_READY, null); 211 mParentApp.registerForLocked(this, EVENT_APP_LOCKED, null); 212 if (DBG) log("SIMRecords X ctor this=" + this); 213 } 214 215 @Override 216 public void dispose() { 217 if (DBG) log("Disposing SIMRecords this=" + this); 218 //Unregister for all events 219 mCi.unregisterForIccRefresh(this); 220 mCi.unSetOnSmsOnSim(this); 221 mParentApp.unregisterForReady(this); 222 mParentApp.unregisterForLocked(this); 223 resetRecords(); 224 super.dispose(); 225 } 226 227 @Override 228 protected void finalize() { 229 if(DBG) log("finalized"); 230 } 231 232 protected void resetRecords() { 233 mImsi = null; 234 mMsisdn = null; 235 mVoiceMailNum = null; 236 mMncLength = UNINITIALIZED; 237 log("setting0 mMncLength" + mMncLength); 238 mIccId = null; 239 // -1 means no EF_SPN found; treat accordingly. 240 mSpnDisplayCondition = -1; 241 mEfMWIS = null; 242 mEfCPHS_MWI = null; 243 mSpdiNetworks = null; 244 mPnnHomeName = null; 245 mGid1 = null; 246 mGid2 = null; 247 248 mAdnCache.reset(); 249 250 log("SIMRecords: onRadioOffOrNotAvailable set 'gsm.sim.operator.numeric' to operator=null"); 251 log("update icc_operator_numeric=" + null); 252 mTelephonyManager.setSimOperatorNumericForPhone(mParentApp.getPhoneId(), ""); 253 mTelephonyManager.setSimOperatorNameForPhone(mParentApp.getPhoneId(), ""); 254 mTelephonyManager.setSimCountryIsoForPhone(mParentApp.getPhoneId(), ""); 255 256 // recordsRequested is set to false indicating that the SIM 257 // read requests made so far are not valid. This is set to 258 // true only when fresh set of read requests are made. 259 mRecordsRequested = false; 260 } 261 262 263 //***** Public Methods 264 265 /** 266 * {@inheritDoc} 267 */ 268 @Override 269 public String getIMSI() { 270 return mImsi; 271 } 272 273 @Override 274 public String getMsisdnNumber() { 275 return mMsisdn; 276 } 277 278 @Override 279 public String getGid1() { 280 return mGid1; 281 } 282 283 @Override 284 public String getGid2() { 285 return mGid2; 286 } 287 288 @Override 289 public UsimServiceTable getUsimServiceTable() { 290 return mUsimServiceTable; 291 } 292 293 private int getExtFromEf(int ef) { 294 int ext; 295 switch (ef) { 296 case EF_MSISDN: 297 /* For USIM apps use EXT5. (TS 31.102 Section 4.2.37) */ 298 if (mParentApp.getType() == AppType.APPTYPE_USIM) { 299 ext = EF_EXT5; 300 } else { 301 ext = EF_EXT1; 302 } 303 break; 304 default: 305 ext = EF_EXT1; 306 } 307 return ext; 308 } 309 310 /** 311 * Set subscriber number to SIM record 312 * 313 * The subscriber number is stored in EF_MSISDN (TS 51.011) 314 * 315 * When the operation is complete, onComplete will be sent to its handler 316 * 317 * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters) 318 * @param number dailing nubmer (up to 20 digits) 319 * if the number starts with '+', then set to international TOA 320 * @param onComplete 321 * onComplete.obj will be an AsyncResult 322 * ((AsyncResult)onComplete.obj).exception == null on success 323 * ((AsyncResult)onComplete.obj).exception != null on fail 324 */ 325 @Override 326 public void setMsisdnNumber(String alphaTag, String number, 327 Message onComplete) { 328 329 // If the SIM card is locked by PIN, we will set EF_MSISDN fail. 330 // In that case, msisdn and msisdnTag should not be update. 331 mNewMsisdn = number; 332 mNewMsisdnTag = alphaTag; 333 334 if(DBG) log("Set MSISDN: " + mNewMsisdnTag + " " + /*mNewMsisdn*/ "xxxxxxx"); 335 336 AdnRecord adn = new AdnRecord(mNewMsisdnTag, mNewMsisdn); 337 338 new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, getExtFromEf(EF_MSISDN), 1, null, 339 obtainMessage(EVENT_SET_MSISDN_DONE, onComplete)); 340 } 341 342 @Override 343 public String getMsisdnAlphaTag() { 344 return mMsisdnTag; 345 } 346 347 @Override 348 public String getVoiceMailNumber() { 349 return mVoiceMailNum; 350 } 351 352 /** 353 * Set voice mail number to SIM record 354 * 355 * The voice mail number can be stored either in EF_MBDN (TS 51.011) or 356 * EF_MAILBOX_CPHS (CPHS 4.2) 357 * 358 * If EF_MBDN is available, store the voice mail number to EF_MBDN 359 * 360 * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS 361 * 362 * So the voice mail number will be stored in both EFs if both are available 363 * 364 * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail. 365 * 366 * When the operation is complete, onComplete will be sent to its handler 367 * 368 * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters) 369 * @param voiceNumber dailing nubmer (upto 20 digits) 370 * if the number is start with '+', then set to international TOA 371 * @param onComplete 372 * onComplete.obj will be an AsyncResult 373 * ((AsyncResult)onComplete.obj).exception == null on success 374 * ((AsyncResult)onComplete.obj).exception != null on fail 375 */ 376 @Override 377 public void setVoiceMailNumber(String alphaTag, String voiceNumber, 378 Message onComplete) { 379 if (mIsVoiceMailFixed) { 380 AsyncResult.forMessage((onComplete)).exception = 381 new IccVmFixedException("Voicemail number is fixed by operator"); 382 onComplete.sendToTarget(); 383 return; 384 } 385 386 mNewVoiceMailNum = voiceNumber; 387 mNewVoiceMailTag = alphaTag; 388 389 AdnRecord adn = new AdnRecord(mNewVoiceMailTag, mNewVoiceMailNum); 390 391 if (mMailboxIndex != 0 && mMailboxIndex != 0xff) { 392 393 new AdnRecordLoader(mFh).updateEF(adn, EF_MBDN, EF_EXT6, 394 mMailboxIndex, null, 395 obtainMessage(EVENT_SET_MBDN_DONE, onComplete)); 396 397 } else if (isCphsMailboxEnabled()) { 398 399 new AdnRecordLoader(mFh).updateEF(adn, EF_MAILBOX_CPHS, 400 EF_EXT1, 1, null, 401 obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE, onComplete)); 402 403 } else { 404 AsyncResult.forMessage((onComplete)).exception = 405 new IccVmNotSupportedException("Update SIM voice mailbox error"); 406 onComplete.sendToTarget(); 407 } 408 } 409 410 @Override 411 public String getVoiceMailAlphaTag() 412 { 413 return mVoiceMailTag; 414 } 415 416 /** 417 * Sets the SIM voice message waiting indicator records 418 * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported 419 * @param countWaiting The number of messages waiting, if known. Use 420 * -1 to indicate that an unknown number of 421 * messages are waiting 422 */ 423 @Override 424 public void 425 setVoiceMessageWaiting(int line, int countWaiting) { 426 if (line != 1) { 427 // only profile 1 is supported 428 return; 429 } 430 431 try { 432 if (mEfMWIS != null) { 433 // TS 51.011 10.3.45 434 435 // lsb of byte 0 is 'voicemail' status 436 mEfMWIS[0] = (byte)((mEfMWIS[0] & 0xfe) 437 | (countWaiting == 0 ? 0 : 1)); 438 439 // byte 1 is the number of voice messages waiting 440 if (countWaiting < 0) { 441 // The spec does not define what this should be 442 // if we don't know the count 443 mEfMWIS[1] = 0; 444 } else { 445 mEfMWIS[1] = (byte) countWaiting; 446 } 447 448 mFh.updateEFLinearFixed( 449 EF_MWIS, 1, mEfMWIS, null, 450 obtainMessage (EVENT_UPDATE_DONE, EF_MWIS, 0)); 451 } 452 453 if (mEfCPHS_MWI != null) { 454 // Refer CPHS4_2.WW6 B4.2.3 455 mEfCPHS_MWI[0] = (byte)((mEfCPHS_MWI[0] & 0xf0) 456 | (countWaiting == 0 ? 0x5 : 0xa)); 457 mFh.updateEFTransparent( 458 EF_VOICE_MAIL_INDICATOR_CPHS, mEfCPHS_MWI, 459 obtainMessage (EVENT_UPDATE_DONE, EF_VOICE_MAIL_INDICATOR_CPHS)); 460 } 461 } catch (ArrayIndexOutOfBoundsException ex) { 462 logw("Error saving voice mail state to SIM. Probably malformed SIM record", ex); 463 } 464 } 465 466 // Validate data is !null and the MSP (Multiple Subscriber Profile) 467 // byte is between 1 and 4. See ETSI TS 131 102 v11.3.0 section 4.2.64. 468 private boolean validEfCfis(byte[] data) { 469 return ((data != null) && (data[0] >= 1) && (data[0] <= 4)); 470 } 471 472 public int getVoiceMessageCount() { 473 boolean voiceMailWaiting = false; 474 int countVoiceMessages = 0; 475 if (mEfMWIS != null) { 476 // Use this data if the EF[MWIS] exists and 477 // has been loaded 478 // Refer TS 51.011 Section 10.3.45 for the content description 479 voiceMailWaiting = ((mEfMWIS[0] & 0x01) != 0); 480 countVoiceMessages = mEfMWIS[1] & 0xff; 481 482 if (voiceMailWaiting && countVoiceMessages == 0) { 483 // Unknown count = -1 484 countVoiceMessages = -1; 485 } 486 if(DBG) log(" VoiceMessageCount from SIM MWIS = " + countVoiceMessages); 487 } else if (mEfCPHS_MWI != null) { 488 // use voice mail count from CPHS 489 int indicator = (int) (mEfCPHS_MWI[0] & 0xf); 490 491 // Refer CPHS4_2.WW6 B4.2.3 492 if (indicator == 0xA) { 493 // Unknown count = -1 494 countVoiceMessages = -1; 495 } else if (indicator == 0x5) { 496 countVoiceMessages = 0; 497 } 498 if(DBG) log(" VoiceMessageCount from SIM CPHS = " + countVoiceMessages); 499 } 500 return countVoiceMessages; 501 } 502 503 /** 504 * {@inheritDoc} 505 */ 506 @Override 507 public boolean getVoiceCallForwardingFlag() { 508 return mCallForwardingEnabled; 509 } 510 511 /** 512 * {@inheritDoc} 513 */ 514 @Override 515 public void setVoiceCallForwardingFlag(int line, boolean enable, String dialNumber) { 516 517 if (line != 1) return; // only line 1 is supported 518 519 mCallForwardingEnabled = enable; 520 521 mRecordsEventsRegistrants.notifyResult(EVENT_CFI); 522 523 try { 524 if (validEfCfis(mEfCfis)) { 525 // lsb is of byte 1 is voice status 526 if (enable) { 527 mEfCfis[1] |= 1; 528 } else { 529 mEfCfis[1] &= 0xfe; 530 } 531 532 log("setVoiceCallForwardingFlag: enable=" + enable 533 + " mEfCfis=" + IccUtils.bytesToHexString(mEfCfis)); 534 535 // Update dialNumber if not empty and CFU is enabled. 536 // Spec reference for EF_CFIS contents, TS 51.011 section 10.3.46. 537 if (enable && !TextUtils.isEmpty(dialNumber)) { 538 log("EF_CFIS: updating cf number, " + dialNumber); 539 byte[] bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(dialNumber); 540 541 System.arraycopy(bcdNumber, 0, mEfCfis, CFIS_TON_NPI_OFFSET, bcdNumber.length); 542 543 mEfCfis[CFIS_BCD_NUMBER_LENGTH_OFFSET] = (byte) (bcdNumber.length); 544 mEfCfis[CFIS_ADN_CAPABILITY_ID_OFFSET] = (byte) 0xFF; 545 mEfCfis[CFIS_ADN_EXTENSION_ID_OFFSET] = (byte) 0xFF; 546 } 547 548 mFh.updateEFLinearFixed( 549 EF_CFIS, 1, mEfCfis, null, 550 obtainMessage (EVENT_UPDATE_DONE, EF_CFIS)); 551 } else { 552 log("setVoiceCallForwardingFlag: ignoring enable=" + enable 553 + " invalid mEfCfis=" + IccUtils.bytesToHexString(mEfCfis)); 554 } 555 556 if (mEfCff != null) { 557 if (enable) { 558 mEfCff[0] = (byte) ((mEfCff[0] & CFF_LINE1_RESET) 559 | CFF_UNCONDITIONAL_ACTIVE); 560 } else { 561 mEfCff[0] = (byte) ((mEfCff[0] & CFF_LINE1_RESET) 562 | CFF_UNCONDITIONAL_DEACTIVE); 563 } 564 565 mFh.updateEFTransparent( 566 EF_CFF_CPHS, mEfCff, 567 obtainMessage (EVENT_UPDATE_DONE, EF_CFF_CPHS)); 568 } 569 } catch (ArrayIndexOutOfBoundsException ex) { 570 logw("Error saving call forwarding flag to SIM. " 571 + "Probably malformed SIM record", ex); 572 573 } 574 } 575 576 /** 577 * Called by STK Service when REFRESH is received. 578 * @param fileChanged indicates whether any files changed 579 * @param fileList if non-null, a list of EF files that changed 580 */ 581 @Override 582 public void onRefresh(boolean fileChanged, int[] fileList) { 583 if (fileChanged) { 584 // A future optimization would be to inspect fileList and 585 // only reload those files that we care about. For now, 586 // just re-fetch all SIM records that we cache. 587 fetchSimRecords(); 588 } 589 } 590 591 /** 592 * {@inheritDoc} 593 */ 594 @Override 595 public String getOperatorNumeric() { 596 if (mImsi == null) { 597 log("getOperatorNumeric: IMSI == null"); 598 return null; 599 } 600 if (mMncLength == UNINITIALIZED || mMncLength == UNKNOWN) { 601 log("getSIMOperatorNumeric: bad mncLength"); 602 return null; 603 } 604 605 // Length = length of MCC + length of MNC 606 // length of mcc = 3 (TS 23.003 Section 2.2) 607 return mImsi.substring(0, 3 + mMncLength); 608 } 609 610 // ***** Overridden from Handler 611 @Override 612 public void handleMessage(Message msg) { 613 AsyncResult ar; 614 AdnRecord adn; 615 616 byte data[]; 617 618 boolean isRecordLoadResponse = false; 619 620 if (mDestroyed.get()) { 621 loge("Received message " + msg + "[" + msg.what + "] " + 622 " while being destroyed. Ignoring."); 623 return; 624 } 625 626 try { switch (msg.what) { 627 case EVENT_APP_READY: 628 onReady(); 629 break; 630 631 case EVENT_APP_LOCKED: 632 onLocked(); 633 break; 634 635 /* IO events */ 636 case EVENT_GET_IMSI_DONE: 637 isRecordLoadResponse = true; 638 639 ar = (AsyncResult)msg.obj; 640 641 if (ar.exception != null) { 642 loge("Exception querying IMSI, Exception:" + ar.exception); 643 break; 644 } 645 646 mImsi = (String) ar.result; 647 648 // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more 649 // than 15 (and usually 15). 650 if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) { 651 loge("invalid IMSI " + mImsi); 652 mImsi = null; 653 } 654 655 log("IMSI: mMncLength=" + mMncLength); 656 log("IMSI: " + mImsi.substring(0, 6) + "xxxxxxx"); 657 658 if (((mMncLength == UNKNOWN) || (mMncLength == 2)) && 659 ((mImsi != null) && (mImsi.length() >= 6))) { 660 String mccmncCode = mImsi.substring(0, 6); 661 for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) { 662 if (mccmnc.equals(mccmncCode)) { 663 mMncLength = 3; 664 log("IMSI: setting1 mMncLength=" + mMncLength); 665 break; 666 } 667 } 668 } 669 670 if (mMncLength == UNKNOWN) { 671 // the SIM has told us all it knows, but it didn't know the mnc length. 672 // guess using the mcc 673 try { 674 int mcc = Integer.parseInt(mImsi.substring(0,3)); 675 mMncLength = MccTable.smallestDigitsMccForMnc(mcc); 676 log("setting2 mMncLength=" + mMncLength); 677 } catch (NumberFormatException e) { 678 mMncLength = UNKNOWN; 679 loge("Corrupt IMSI! setting3 mMncLength=" + mMncLength); 680 } 681 } 682 683 if (mMncLength != UNKNOWN && mMncLength != UNINITIALIZED) { 684 log("update mccmnc=" + mImsi.substring(0, 3 + mMncLength)); 685 // finally have both the imsi and the mncLength and can parse the imsi properly 686 MccTable.updateMccMncConfiguration(mContext, 687 mImsi.substring(0, 3 + mMncLength), false); 688 } 689 mImsiReadyRegistrants.notifyRegistrants(); 690 break; 691 692 case EVENT_GET_MBI_DONE: 693 boolean isValidMbdn; 694 isRecordLoadResponse = true; 695 696 ar = (AsyncResult)msg.obj; 697 data = (byte[]) ar.result; 698 699 isValidMbdn = false; 700 if (ar.exception == null) { 701 // Refer TS 51.011 Section 10.3.44 for content details 702 log("EF_MBI: " + IccUtils.bytesToHexString(data)); 703 704 // Voice mail record number stored first 705 mMailboxIndex = data[0] & 0xff; 706 707 // check if dailing numbe id valid 708 if (mMailboxIndex != 0 && mMailboxIndex != 0xff) { 709 log("Got valid mailbox number for MBDN"); 710 isValidMbdn = true; 711 } 712 } 713 714 // one more record to load 715 mRecordsToLoad += 1; 716 717 if (isValidMbdn) { 718 // Note: MBDN was not included in NUM_OF_SIM_RECORDS_LOADED 719 new AdnRecordLoader(mFh).loadFromEF(EF_MBDN, EF_EXT6, 720 mMailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE)); 721 } else { 722 // If this EF not present, try mailbox as in CPHS standard 723 // CPHS (CPHS4_2.WW6) is a european standard. 724 new AdnRecordLoader(mFh).loadFromEF(EF_MAILBOX_CPHS, 725 EF_EXT1, 1, 726 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE)); 727 } 728 729 break; 730 case EVENT_GET_CPHS_MAILBOX_DONE: 731 case EVENT_GET_MBDN_DONE: 732 //Resetting the voice mail number and voice mail tag to null 733 //as these should be updated from the data read from EF_MBDN. 734 //If they are not reset, incase of invalid data/exception these 735 //variables are retaining their previous values and are 736 //causing invalid voice mailbox info display to user. 737 mVoiceMailNum = null; 738 mVoiceMailTag = null; 739 isRecordLoadResponse = true; 740 741 ar = (AsyncResult)msg.obj; 742 743 if (ar.exception != null) { 744 745 log("Invalid or missing EF" 746 + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? "[MAILBOX]" : "[MBDN]")); 747 748 // Bug #645770 fall back to CPHS 749 // FIXME should use SST to decide 750 751 if (msg.what == EVENT_GET_MBDN_DONE) { 752 //load CPHS on fail... 753 // FIXME right now, only load line1's CPHS voice mail entry 754 755 mRecordsToLoad += 1; 756 new AdnRecordLoader(mFh).loadFromEF( 757 EF_MAILBOX_CPHS, EF_EXT1, 1, 758 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE)); 759 } 760 break; 761 } 762 763 adn = (AdnRecord)ar.result; 764 765 log("VM: " + adn + 766 ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? " EF[MAILBOX]" : " EF[MBDN]")); 767 768 if (adn.isEmpty() && msg.what == EVENT_GET_MBDN_DONE) { 769 // Bug #645770 fall back to CPHS 770 // FIXME should use SST to decide 771 // FIXME right now, only load line1's CPHS voice mail entry 772 mRecordsToLoad += 1; 773 new AdnRecordLoader(mFh).loadFromEF( 774 EF_MAILBOX_CPHS, EF_EXT1, 1, 775 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE)); 776 777 break; 778 } 779 780 mVoiceMailNum = adn.getNumber(); 781 mVoiceMailTag = adn.getAlphaTag(); 782 break; 783 784 case EVENT_GET_MSISDN_DONE: 785 isRecordLoadResponse = true; 786 787 ar = (AsyncResult)msg.obj; 788 789 if (ar.exception != null) { 790 log("Invalid or missing EF[MSISDN]"); 791 break; 792 } 793 794 adn = (AdnRecord)ar.result; 795 796 mMsisdn = adn.getNumber(); 797 mMsisdnTag = adn.getAlphaTag(); 798 799 log("MSISDN: " + /*mMsisdn*/ "xxxxxxx"); 800 break; 801 802 case EVENT_SET_MSISDN_DONE: 803 isRecordLoadResponse = false; 804 ar = (AsyncResult)msg.obj; 805 806 if (ar.exception == null) { 807 mMsisdn = mNewMsisdn; 808 mMsisdnTag = mNewMsisdnTag; 809 log("Success to update EF[MSISDN]"); 810 } 811 812 if (ar.userObj != null) { 813 AsyncResult.forMessage(((Message) ar.userObj)).exception 814 = ar.exception; 815 ((Message) ar.userObj).sendToTarget(); 816 } 817 break; 818 819 case EVENT_GET_MWIS_DONE: 820 isRecordLoadResponse = true; 821 822 ar = (AsyncResult)msg.obj; 823 data = (byte[])ar.result; 824 825 if(DBG) log("EF_MWIS : " + IccUtils.bytesToHexString(data)); 826 827 if (ar.exception != null) { 828 if(DBG) log("EVENT_GET_MWIS_DONE exception = " 829 + ar.exception); 830 break; 831 } 832 833 if ((data[0] & 0xff) == 0xff) { 834 if(DBG) log("SIMRecords: Uninitialized record MWIS"); 835 break; 836 } 837 838 mEfMWIS = data; 839 break; 840 841 case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE: 842 isRecordLoadResponse = true; 843 844 ar = (AsyncResult)msg.obj; 845 data = (byte[])ar.result; 846 847 if(DBG) log("EF_CPHS_MWI: " + IccUtils.bytesToHexString(data)); 848 849 if (ar.exception != null) { 850 if(DBG) log("EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE exception = " 851 + ar.exception); 852 break; 853 } 854 855 mEfCPHS_MWI = data; 856 break; 857 858 case EVENT_GET_ICCID_DONE: 859 isRecordLoadResponse = true; 860 861 ar = (AsyncResult)msg.obj; 862 data = (byte[])ar.result; 863 864 if (ar.exception != null) { 865 break; 866 } 867 868 mIccId = IccUtils.bcdToString(data, 0, data.length); 869 870 log("iccid: " + mIccId); 871 872 break; 873 874 875 case EVENT_GET_AD_DONE: 876 try { 877 isRecordLoadResponse = true; 878 879 ar = (AsyncResult)msg.obj; 880 data = (byte[])ar.result; 881 882 if (ar.exception != null) { 883 break; 884 } 885 886 log("EF_AD: " + IccUtils.bytesToHexString(data)); 887 888 if (data.length < 3) { 889 log("Corrupt AD data on SIM"); 890 break; 891 } 892 893 if (data.length == 3) { 894 log("MNC length not present in EF_AD"); 895 break; 896 } 897 898 mMncLength = data[3] & 0xf; 899 log("setting4 mMncLength=" + mMncLength); 900 901 if (mMncLength == 0xf) { 902 mMncLength = UNKNOWN; 903 log("setting5 mMncLength=" + mMncLength); 904 } 905 } finally { 906 if (((mMncLength == UNINITIALIZED) || (mMncLength == UNKNOWN) || 907 (mMncLength == 2)) && ((mImsi != null) && (mImsi.length() >= 6))) { 908 String mccmncCode = mImsi.substring(0, 6); 909 log("mccmncCode=" + mccmncCode); 910 for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) { 911 if (mccmnc.equals(mccmncCode)) { 912 mMncLength = 3; 913 log("setting6 mMncLength=" + mMncLength); 914 break; 915 } 916 } 917 } 918 919 if (mMncLength == UNKNOWN || mMncLength == UNINITIALIZED) { 920 if (mImsi != null) { 921 try { 922 int mcc = Integer.parseInt(mImsi.substring(0,3)); 923 924 mMncLength = MccTable.smallestDigitsMccForMnc(mcc); 925 log("setting7 mMncLength=" + mMncLength); 926 } catch (NumberFormatException e) { 927 mMncLength = UNKNOWN; 928 loge("Corrupt IMSI! setting8 mMncLength=" + mMncLength); 929 } 930 } else { 931 // Indicate we got this info, but it didn't contain the length. 932 mMncLength = UNKNOWN; 933 log("MNC length not present in EF_AD setting9 mMncLength=" + mMncLength); 934 } 935 } 936 if (mImsi != null && mMncLength != UNKNOWN) { 937 // finally have both imsi and the length of the mnc and can parse 938 // the imsi properly 939 log("update mccmnc=" + mImsi.substring(0, 3 + mMncLength)); 940 MccTable.updateMccMncConfiguration(mContext, 941 mImsi.substring(0, 3 + mMncLength), false); 942 } 943 } 944 break; 945 946 case EVENT_GET_SPN_DONE: 947 isRecordLoadResponse = true; 948 ar = (AsyncResult) msg.obj; 949 getSpnFsm(false, ar); 950 break; 951 952 case EVENT_GET_CFF_DONE: 953 isRecordLoadResponse = true; 954 955 ar = (AsyncResult) msg.obj; 956 data = (byte[]) ar.result; 957 958 if (ar.exception != null) { 959 break; 960 } 961 962 log("EF_CFF_CPHS: " + IccUtils.bytesToHexString(data)); 963 mEfCff = data; 964 965 // if EF_CFIS is valid, prefer it to EF_CFF_CPHS 966 if (!validEfCfis(mEfCfis)) { 967 mCallForwardingEnabled = 968 ((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE); 969 970 mRecordsEventsRegistrants.notifyResult(EVENT_CFI); 971 } else { 972 log("EVENT_GET_CFF_DONE: EF_CFIS is valid, ignoring EF_CFF_CPHS"); 973 } 974 break; 975 976 case EVENT_GET_SPDI_DONE: 977 isRecordLoadResponse = true; 978 979 ar = (AsyncResult)msg.obj; 980 data = (byte[])ar.result; 981 982 if (ar.exception != null) { 983 break; 984 } 985 986 parseEfSpdi(data); 987 break; 988 989 case EVENT_UPDATE_DONE: 990 ar = (AsyncResult)msg.obj; 991 if (ar.exception != null) { 992 logw("update failed. ", ar.exception); 993 } 994 break; 995 996 case EVENT_GET_PNN_DONE: 997 isRecordLoadResponse = true; 998 999 ar = (AsyncResult)msg.obj; 1000 data = (byte[])ar.result; 1001 1002 if (ar.exception != null) { 1003 break; 1004 } 1005 1006 SimTlv tlv = new SimTlv(data, 0, data.length); 1007 1008 for ( ; tlv.isValidObject() ; tlv.nextObject()) { 1009 if (tlv.getTag() == TAG_FULL_NETWORK_NAME) { 1010 mPnnHomeName 1011 = IccUtils.networkNameToString( 1012 tlv.getData(), 0, tlv.getData().length); 1013 break; 1014 } 1015 } 1016 break; 1017 1018 case EVENT_GET_ALL_SMS_DONE: 1019 isRecordLoadResponse = true; 1020 1021 ar = (AsyncResult)msg.obj; 1022 if (ar.exception != null) 1023 break; 1024 1025 handleSmses((ArrayList<byte []>) ar.result); 1026 break; 1027 1028 case EVENT_MARK_SMS_READ_DONE: 1029 Rlog.i("ENF", "marked read: sms " + msg.arg1); 1030 break; 1031 1032 1033 case EVENT_SMS_ON_SIM: 1034 isRecordLoadResponse = false; 1035 1036 ar = (AsyncResult)msg.obj; 1037 1038 int[] index = (int[])ar.result; 1039 1040 if (ar.exception != null || index.length != 1) { 1041 loge("Error on SMS_ON_SIM with exp " 1042 + ar.exception + " length " + index.length); 1043 } else { 1044 log("READ EF_SMS RECORD index=" + index[0]); 1045 mFh.loadEFLinearFixed(EF_SMS,index[0], 1046 obtainMessage(EVENT_GET_SMS_DONE)); 1047 } 1048 break; 1049 1050 case EVENT_GET_SMS_DONE: 1051 isRecordLoadResponse = false; 1052 ar = (AsyncResult)msg.obj; 1053 if (ar.exception == null) { 1054 handleSms((byte[])ar.result); 1055 } else { 1056 loge("Error on GET_SMS with exp " + ar.exception); 1057 } 1058 break; 1059 case EVENT_GET_SST_DONE: 1060 isRecordLoadResponse = true; 1061 1062 ar = (AsyncResult)msg.obj; 1063 data = (byte[])ar.result; 1064 1065 if (ar.exception != null) { 1066 break; 1067 } 1068 1069 mUsimServiceTable = new UsimServiceTable(data); 1070 if (DBG) log("SST: " + mUsimServiceTable); 1071 break; 1072 1073 case EVENT_GET_INFO_CPHS_DONE: 1074 isRecordLoadResponse = true; 1075 1076 ar = (AsyncResult)msg.obj; 1077 1078 if (ar.exception != null) { 1079 break; 1080 } 1081 1082 mCphsInfo = (byte[])ar.result; 1083 1084 if (DBG) log("iCPHS: " + IccUtils.bytesToHexString(mCphsInfo)); 1085 break; 1086 1087 case EVENT_SET_MBDN_DONE: 1088 isRecordLoadResponse = false; 1089 ar = (AsyncResult)msg.obj; 1090 1091 if (DBG) log("EVENT_SET_MBDN_DONE ex:" + ar.exception); 1092 if (ar.exception == null) { 1093 mVoiceMailNum = mNewVoiceMailNum; 1094 mVoiceMailTag = mNewVoiceMailTag; 1095 } 1096 1097 if (isCphsMailboxEnabled()) { 1098 adn = new AdnRecord(mVoiceMailTag, mVoiceMailNum); 1099 Message onCphsCompleted = (Message) ar.userObj; 1100 1101 /* write to cphs mailbox whenever it is available but 1102 * we only need notify caller once if both updating are 1103 * successful. 1104 * 1105 * so if set_mbdn successful, notify caller here and set 1106 * onCphsCompleted to null 1107 */ 1108 if (ar.exception == null && ar.userObj != null) { 1109 AsyncResult.forMessage(((Message) ar.userObj)).exception 1110 = null; 1111 ((Message) ar.userObj).sendToTarget(); 1112 1113 if (DBG) log("Callback with MBDN successful."); 1114 1115 onCphsCompleted = null; 1116 } 1117 1118 new AdnRecordLoader(mFh). 1119 updateEF(adn, EF_MAILBOX_CPHS, EF_EXT1, 1, null, 1120 obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE, 1121 onCphsCompleted)); 1122 } else { 1123 if (ar.userObj != null) { 1124 Resources resource = Resources.getSystem(); 1125 if (ar.exception != null && resource.getBoolean(com.android.internal. 1126 R.bool.editable_voicemailnumber)) { 1127 // GSMPhone will store vm number on device 1128 // when IccVmNotSupportedException occurred 1129 AsyncResult.forMessage(((Message) ar.userObj)).exception 1130 = new IccVmNotSupportedException( 1131 "Update SIM voice mailbox error"); 1132 } else { 1133 AsyncResult.forMessage(((Message) ar.userObj)).exception 1134 = ar.exception; 1135 } 1136 ((Message) ar.userObj).sendToTarget(); 1137 } 1138 } 1139 break; 1140 case EVENT_SET_CPHS_MAILBOX_DONE: 1141 isRecordLoadResponse = false; 1142 ar = (AsyncResult)msg.obj; 1143 if(ar.exception == null) { 1144 mVoiceMailNum = mNewVoiceMailNum; 1145 mVoiceMailTag = mNewVoiceMailTag; 1146 } else { 1147 if (DBG) log("Set CPHS MailBox with exception: " 1148 + ar.exception); 1149 } 1150 if (ar.userObj != null) { 1151 if (DBG) log("Callback with CPHS MB successful."); 1152 AsyncResult.forMessage(((Message) ar.userObj)).exception 1153 = ar.exception; 1154 ((Message) ar.userObj).sendToTarget(); 1155 } 1156 break; 1157 case EVENT_SIM_REFRESH: 1158 isRecordLoadResponse = false; 1159 ar = (AsyncResult)msg.obj; 1160 if (DBG) log("Sim REFRESH with exception: " + ar.exception); 1161 if (ar.exception == null) { 1162 handleSimRefresh((IccRefreshResponse)ar.result); 1163 } 1164 break; 1165 case EVENT_GET_CFIS_DONE: 1166 isRecordLoadResponse = true; 1167 1168 ar = (AsyncResult)msg.obj; 1169 data = (byte[])ar.result; 1170 1171 if (ar.exception != null) { 1172 break; 1173 } 1174 1175 log("EF_CFIS: " + IccUtils.bytesToHexString(data)); 1176 1177 if (validEfCfis(data)) { 1178 mEfCfis = data; 1179 1180 // Refer TS 51.011 Section 10.3.46 for the content description 1181 mCallForwardingEnabled = ((data[1] & 0x01) != 0); 1182 log("EF_CFIS: callForwardingEnabled=" + mCallForwardingEnabled); 1183 1184 mRecordsEventsRegistrants.notifyResult(EVENT_CFI); 1185 } else { 1186 log("EF_CFIS: invalid data=" + IccUtils.bytesToHexString(data)); 1187 } 1188 break; 1189 1190 case EVENT_GET_CSP_CPHS_DONE: 1191 isRecordLoadResponse = true; 1192 1193 ar = (AsyncResult)msg.obj; 1194 1195 if (ar.exception != null) { 1196 loge("Exception in fetching EF_CSP data " + ar.exception); 1197 break; 1198 } 1199 1200 data = (byte[])ar.result; 1201 1202 log("EF_CSP: " + IccUtils.bytesToHexString(data)); 1203 handleEfCspData(data); 1204 break; 1205 1206 case EVENT_GET_GID1_DONE: 1207 isRecordLoadResponse = true; 1208 1209 ar = (AsyncResult)msg.obj; 1210 data =(byte[])ar.result; 1211 1212 if (ar.exception != null) { 1213 loge("Exception in get GID1 " + ar.exception); 1214 mGid1 = null; 1215 break; 1216 } 1217 mGid1 = IccUtils.bytesToHexString(data); 1218 log("GID1: " + mGid1); 1219 1220 break; 1221 1222 case EVENT_GET_GID2_DONE: 1223 isRecordLoadResponse = true; 1224 1225 ar = (AsyncResult)msg.obj; 1226 data =(byte[])ar.result; 1227 1228 if (ar.exception != null) { 1229 loge("Exception in get GID2 " + ar.exception); 1230 mGid2 = null; 1231 break; 1232 } 1233 mGid2 = IccUtils.bytesToHexString(data); 1234 log("GID2: " + mGid2); 1235 1236 break; 1237 1238 default: 1239 super.handleMessage(msg); // IccRecords handles generic record load responses 1240 1241 }}catch (RuntimeException exc) { 1242 // I don't want these exceptions to be fatal 1243 logw("Exception parsing SIM record", exc); 1244 } finally { 1245 // Count up record load responses even if they are fails 1246 if (isRecordLoadResponse) { 1247 onRecordLoaded(); 1248 } 1249 } 1250 } 1251 1252 private class EfPlLoaded implements IccRecordLoaded { 1253 public String getEfName() { 1254 return "EF_PL"; 1255 } 1256 1257 public void onRecordLoaded(AsyncResult ar) { 1258 mEfPl = (byte[]) ar.result; 1259 if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEfPl)); 1260 } 1261 } 1262 1263 private class EfUsimLiLoaded implements IccRecordLoaded { 1264 public String getEfName() { 1265 return "EF_LI"; 1266 } 1267 1268 public void onRecordLoaded(AsyncResult ar) { 1269 mEfLi = (byte[]) ar.result; 1270 if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEfLi)); 1271 } 1272 } 1273 1274 private void handleFileUpdate(int efid) { 1275 switch(efid) { 1276 case EF_MBDN: 1277 mRecordsToLoad++; 1278 new AdnRecordLoader(mFh).loadFromEF(EF_MBDN, EF_EXT6, 1279 mMailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE)); 1280 break; 1281 case EF_MAILBOX_CPHS: 1282 mRecordsToLoad++; 1283 new AdnRecordLoader(mFh).loadFromEF(EF_MAILBOX_CPHS, EF_EXT1, 1284 1, obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE)); 1285 break; 1286 case EF_CSP_CPHS: 1287 mRecordsToLoad++; 1288 log("[CSP] SIM Refresh for EF_CSP_CPHS"); 1289 mFh.loadEFTransparent(EF_CSP_CPHS, 1290 obtainMessage(EVENT_GET_CSP_CPHS_DONE)); 1291 break; 1292 case EF_FDN: 1293 if (DBG) log("SIM Refresh called for EF_FDN"); 1294 mParentApp.queryFdn(); 1295 break; 1296 case EF_MSISDN: 1297 mRecordsToLoad++; 1298 log("SIM Refresh called for EF_MSISDN"); 1299 new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1, 1300 obtainMessage(EVENT_GET_MSISDN_DONE)); 1301 break; 1302 case EF_CFIS: 1303 mRecordsToLoad++; 1304 log("SIM Refresh called for EF_CFIS"); 1305 mFh.loadEFLinearFixed(EF_CFIS, 1306 1, obtainMessage(EVENT_GET_CFIS_DONE)); 1307 break; 1308 case EF_CFF_CPHS: 1309 mRecordsToLoad++; 1310 log("SIM Refresh called for EF_CFF_CPHS"); 1311 mFh.loadEFTransparent(EF_CFF_CPHS, 1312 obtainMessage(EVENT_GET_CFF_DONE)); 1313 break; 1314 default: 1315 // For now, fetch all records if this is not a 1316 // voicemail number. 1317 // TODO: Handle other cases, instead of fetching all. 1318 mAdnCache.reset(); 1319 fetchSimRecords(); 1320 break; 1321 } 1322 } 1323 1324 private void handleSimRefresh(IccRefreshResponse refreshResponse){ 1325 if (refreshResponse == null) { 1326 if (DBG) log("handleSimRefresh received without input"); 1327 return; 1328 } 1329 1330 if (refreshResponse.aid != null && 1331 !refreshResponse.aid.equals(mParentApp.getAid())) { 1332 // This is for different app. Ignore. 1333 return; 1334 } 1335 1336 switch (refreshResponse.refreshResult) { 1337 case IccRefreshResponse.REFRESH_RESULT_FILE_UPDATE: 1338 if (DBG) log("handleSimRefresh with SIM_FILE_UPDATED"); 1339 handleFileUpdate(refreshResponse.efId); 1340 break; 1341 case IccRefreshResponse.REFRESH_RESULT_INIT: 1342 if (DBG) log("handleSimRefresh with SIM_REFRESH_INIT"); 1343 // need to reload all files (that we care about) 1344 onIccRefreshInit(); 1345 break; 1346 case IccRefreshResponse.REFRESH_RESULT_RESET: 1347 // Refresh reset is handled by the UiccCard object. 1348 if (DBG) log("handleSimRefresh with SIM_REFRESH_RESET"); 1349 break; 1350 default: 1351 // unknown refresh operation 1352 if (DBG) log("handleSimRefresh with unknown operation"); 1353 break; 1354 } 1355 } 1356 1357 /** 1358 * Dispatch 3GPP format message to registrant ({@code GSMPhone} or {@code CDMALTEPhone}) 1359 * to pass to the 3GPP SMS dispatcher for delivery. 1360 */ 1361 private int dispatchGsmMessage(SmsMessage message) { 1362 mNewSmsRegistrants.notifyResult(message); 1363 return 0; 1364 } 1365 1366 private void handleSms(byte[] ba) { 1367 if (ba[0] != 0) 1368 Rlog.d("ENF", "status : " + ba[0]); 1369 1370 // 3GPP TS 51.011 v5.0.0 (20011-12) 10.5.3 1371 // 3 == "received by MS from network; message to be read" 1372 if (ba[0] == 3) { 1373 int n = ba.length; 1374 1375 // Note: Data may include trailing FF's. That's OK; message 1376 // should still parse correctly. 1377 byte[] pdu = new byte[n - 1]; 1378 System.arraycopy(ba, 1, pdu, 0, n - 1); 1379 SmsMessage message = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP); 1380 1381 dispatchGsmMessage(message); 1382 } 1383 } 1384 1385 1386 private void handleSmses(ArrayList<byte[]> messages) { 1387 int count = messages.size(); 1388 1389 for (int i = 0; i < count; i++) { 1390 byte[] ba = messages.get(i); 1391 1392 if (ba[0] != 0) 1393 Rlog.i("ENF", "status " + i + ": " + ba[0]); 1394 1395 // 3GPP TS 51.011 v5.0.0 (20011-12) 10.5.3 1396 // 3 == "received by MS from network; message to be read" 1397 1398 if (ba[0] == 3) { 1399 int n = ba.length; 1400 1401 // Note: Data may include trailing FF's. That's OK; message 1402 // should still parse correctly. 1403 byte[] pdu = new byte[n - 1]; 1404 System.arraycopy(ba, 1, pdu, 0, n - 1); 1405 SmsMessage message = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP); 1406 1407 dispatchGsmMessage(message); 1408 1409 // 3GPP TS 51.011 v5.0.0 (20011-12) 10.5.3 1410 // 1 == "received by MS from network; message read" 1411 1412 ba[0] = 1; 1413 1414 if (false) { // FIXME: writing seems to crash RdoServD 1415 mFh.updateEFLinearFixed(EF_SMS, 1416 i, ba, null, obtainMessage(EVENT_MARK_SMS_READ_DONE, i)); 1417 } 1418 } 1419 } 1420 } 1421 1422 @Override 1423 protected void onRecordLoaded() { 1424 // One record loaded successfully or failed, In either case 1425 // we need to update the recordsToLoad count 1426 mRecordsToLoad -= 1; 1427 if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested); 1428 1429 if (mRecordsToLoad == 0 && mRecordsRequested == true) { 1430 onAllRecordsLoaded(); 1431 } else if (mRecordsToLoad < 0) { 1432 loge("recordsToLoad <0, programmer error suspected"); 1433 mRecordsToLoad = 0; 1434 } 1435 } 1436 1437 @Override 1438 protected void onAllRecordsLoaded() { 1439 if (DBG) log("record load complete"); 1440 1441 Resources resource = Resources.getSystem(); 1442 if (resource.getBoolean(com.android.internal.R.bool.config_use_sim_language_file)) { 1443 setSimLanguage(mEfLi, mEfPl); 1444 } else { 1445 if (DBG) log ("Not using EF LI/EF PL"); 1446 } 1447 1448 if (mParentApp.getState() == AppState.APPSTATE_PIN || 1449 mParentApp.getState() == AppState.APPSTATE_PUK) { 1450 // reset recordsRequested, since sim is not loaded really 1451 mRecordsRequested = false; 1452 // lock state, only update language 1453 return ; 1454 } 1455 1456 // Some fields require more than one SIM record to set 1457 1458 String operator = getOperatorNumeric(); 1459 if (!TextUtils.isEmpty(operator)) { 1460 log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" + 1461 operator + "'"); 1462 log("update icc_operator_numeric=" + operator); 1463 mTelephonyManager.setSimOperatorNumericForPhone( 1464 mParentApp.getPhoneId(), operator); 1465 final SubscriptionController subController = SubscriptionController.getInstance(); 1466 subController.setMccMnc(operator, subController.getDefaultSmsSubId()); 1467 } else { 1468 log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping"); 1469 } 1470 1471 if (!TextUtils.isEmpty(mImsi)) { 1472 log("onAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + mImsi) : "")); 1473 mTelephonyManager.setSimCountryIsoForPhone( 1474 mParentApp.getPhoneId(), MccTable.countryCodeForMcc( 1475 Integer.parseInt(mImsi.substring(0,3)))); 1476 } else { 1477 log("onAllRecordsLoaded empty imsi skipping setting mcc"); 1478 } 1479 1480 setVoiceMailByCountry(operator); 1481 setSpnFromConfig(operator); 1482 1483 mRecordsLoadedRegistrants.notifyRegistrants( 1484 new AsyncResult(null, null, null)); 1485 } 1486 1487 //***** Private methods 1488 1489 private void setSpnFromConfig(String carrier) { 1490 if (mSpnOverride.containsCarrier(carrier)) { 1491 setServiceProviderName(mSpnOverride.getSpn(carrier)); 1492 mTelephonyManager.setSimOperatorNameForPhone( 1493 mParentApp.getPhoneId(), getServiceProviderName()); 1494 } 1495 } 1496 1497 1498 private void setVoiceMailByCountry (String spn) { 1499 if (mVmConfig.containsCarrier(spn)) { 1500 mIsVoiceMailFixed = true; 1501 mVoiceMailNum = mVmConfig.getVoiceMailNumber(spn); 1502 mVoiceMailTag = mVmConfig.getVoiceMailTag(spn); 1503 } 1504 } 1505 1506 @Override 1507 public void onReady() { 1508 fetchSimRecords(); 1509 } 1510 1511 private void onLocked() { 1512 if (DBG) log("only fetch EF_LI and EF_PL in lock state"); 1513 loadEfLiAndEfPl(); 1514 } 1515 1516 private void loadEfLiAndEfPl() { 1517 if (mParentApp.getType() == AppType.APPTYPE_USIM) { 1518 mRecordsRequested = true; 1519 mFh.loadEFTransparent(EF_LI, 1520 obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfUsimLiLoaded())); 1521 mRecordsToLoad++; 1522 1523 mFh.loadEFTransparent(EF_PL, 1524 obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded())); 1525 mRecordsToLoad++; 1526 } 1527 } 1528 1529 protected void fetchSimRecords() { 1530 mRecordsRequested = true; 1531 1532 if (DBG) log("fetchSimRecords " + mRecordsToLoad); 1533 1534 mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE)); 1535 mRecordsToLoad++; 1536 1537 mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); 1538 mRecordsToLoad++; 1539 1540 // FIXME should examine EF[MSISDN]'s capability configuration 1541 // to determine which is the voice/data/fax line 1542 new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1, 1543 obtainMessage(EVENT_GET_MSISDN_DONE)); 1544 mRecordsToLoad++; 1545 1546 // Record number is subscriber profile 1547 mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE)); 1548 mRecordsToLoad++; 1549 1550 mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE)); 1551 mRecordsToLoad++; 1552 1553 // Record number is subscriber profile 1554 mFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE)); 1555 mRecordsToLoad++; 1556 1557 1558 // Also load CPHS-style voice mail indicator, which stores 1559 // the same info as EF[MWIS]. If both exist, both are updated 1560 // but the EF[MWIS] data is preferred 1561 // Please note this must be loaded after EF[MWIS] 1562 mFh.loadEFTransparent( 1563 EF_VOICE_MAIL_INDICATOR_CPHS, 1564 obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE)); 1565 mRecordsToLoad++; 1566 1567 // Same goes for Call Forward Status indicator: fetch both 1568 // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred. 1569 mFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE)); 1570 mRecordsToLoad++; 1571 mFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE)); 1572 mRecordsToLoad++; 1573 1574 1575 getSpnFsm(true, null); 1576 1577 mFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE)); 1578 mRecordsToLoad++; 1579 1580 mFh.loadEFLinearFixed(EF_PNN, 1, obtainMessage(EVENT_GET_PNN_DONE)); 1581 mRecordsToLoad++; 1582 1583 mFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE)); 1584 mRecordsToLoad++; 1585 1586 mFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE)); 1587 mRecordsToLoad++; 1588 1589 mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE)); 1590 mRecordsToLoad++; 1591 1592 mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE)); 1593 mRecordsToLoad++; 1594 1595 mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE)); 1596 mRecordsToLoad++; 1597 1598 loadEfLiAndEfPl(); 1599 1600 // XXX should seek instead of examining them all 1601 if (false) { // XXX 1602 mFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE)); 1603 mRecordsToLoad++; 1604 } 1605 1606 if (CRASH_RIL) { 1607 String sms = "0107912160130310f20404d0110041007030208054832b0120" 1608 + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 1609 + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 1610 + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 1611 + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 1612 + "ffffffffffffffffffffffffffffff"; 1613 byte[] ba = IccUtils.hexStringToBytes(sms); 1614 1615 mFh.updateEFLinearFixed(EF_SMS, 1, ba, null, 1616 obtainMessage(EVENT_MARK_SMS_READ_DONE, 1)); 1617 } 1618 if (DBG) log("fetchSimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested); 1619 } 1620 1621 /** 1622 * Returns the SpnDisplayRule based on settings on the SIM and the 1623 * specified plmn (currently-registered PLMN). See TS 22.101 Annex A 1624 * and TS 51.011 10.3.11 for details. 1625 * 1626 * If the SPN is not found on the SIM or is empty, the rule is 1627 * always PLMN_ONLY. 1628 */ 1629 @Override 1630 public int getDisplayRule(String plmn) { 1631 int rule; 1632 1633 if (mParentApp != null && mParentApp.getUiccCard() != null && 1634 mParentApp.getUiccCard().getOperatorBrandOverride() != null) { 1635 // If the operator has been overridden, treat it as the SPN file on the SIM did not exist. 1636 rule = SPN_RULE_SHOW_PLMN; 1637 } else if (TextUtils.isEmpty(getServiceProviderName()) || mSpnDisplayCondition == -1) { 1638 // No EF_SPN content was found on the SIM, or not yet loaded. Just show ONS. 1639 rule = SPN_RULE_SHOW_PLMN; 1640 } else if (isOnMatchingPlmn(plmn)) { 1641 rule = SPN_RULE_SHOW_SPN; 1642 if ((mSpnDisplayCondition & 0x01) == 0x01) { 1643 // ONS required when registered to HPLMN or PLMN in EF_SPDI 1644 rule |= SPN_RULE_SHOW_PLMN; 1645 } 1646 } else { 1647 rule = SPN_RULE_SHOW_PLMN; 1648 if ((mSpnDisplayCondition & 0x02) == 0x00) { 1649 // SPN required if not registered to HPLMN or PLMN in EF_SPDI 1650 rule |= SPN_RULE_SHOW_SPN; 1651 } 1652 } 1653 return rule; 1654 } 1655 1656 /** 1657 * Checks if plmn is HPLMN or on the spdiNetworks list. 1658 */ 1659 private boolean isOnMatchingPlmn(String plmn) { 1660 if (plmn == null) return false; 1661 1662 if (plmn.equals(getOperatorNumeric())) { 1663 return true; 1664 } 1665 1666 if (mSpdiNetworks != null) { 1667 for (String spdiNet : mSpdiNetworks) { 1668 if (plmn.equals(spdiNet)) { 1669 return true; 1670 } 1671 } 1672 } 1673 return false; 1674 } 1675 1676 /** 1677 * States of Get SPN Finite State Machine which only used by getSpnFsm() 1678 */ 1679 private enum GetSpnFsmState { 1680 IDLE, // No initialized 1681 INIT, // Start FSM 1682 READ_SPN_3GPP, // Load EF_SPN firstly 1683 READ_SPN_CPHS, // Load EF_SPN_CPHS secondly 1684 READ_SPN_SHORT_CPHS // Load EF_SPN_SHORT_CPHS last 1685 } 1686 1687 /** 1688 * Finite State Machine to load Service Provider Name , which can be stored 1689 * in either EF_SPN (3GPP), EF_SPN_CPHS, or EF_SPN_SHORT_CPHS (CPHS4.2) 1690 * 1691 * After starting, FSM will search SPN EFs in order and stop after finding 1692 * the first valid SPN 1693 * 1694 * If the FSM gets restart while waiting for one of 1695 * SPN EFs results (i.e. a SIM refresh occurs after issuing 1696 * read EF_CPHS_SPN), it will re-initialize only after 1697 * receiving and discarding the unfinished SPN EF result. 1698 * 1699 * @param start set true only for initialize loading 1700 * @param ar the AsyncResult from loadEFTransparent 1701 * ar.exception holds exception in error 1702 * ar.result is byte[] for data in success 1703 */ 1704 private void getSpnFsm(boolean start, AsyncResult ar) { 1705 byte[] data; 1706 1707 if (start) { 1708 // Check previous state to see if there is outstanding 1709 // SPN read 1710 if(mSpnState == GetSpnFsmState.READ_SPN_3GPP || 1711 mSpnState == GetSpnFsmState.READ_SPN_CPHS || 1712 mSpnState == GetSpnFsmState.READ_SPN_SHORT_CPHS || 1713 mSpnState == GetSpnFsmState.INIT) { 1714 // Set INIT then return so the INIT code 1715 // will run when the outstanding read done. 1716 mSpnState = GetSpnFsmState.INIT; 1717 return; 1718 } else { 1719 mSpnState = GetSpnFsmState.INIT; 1720 } 1721 } 1722 1723 switch(mSpnState){ 1724 case INIT: 1725 setServiceProviderName(null); 1726 1727 mFh.loadEFTransparent(EF_SPN, 1728 obtainMessage(EVENT_GET_SPN_DONE)); 1729 mRecordsToLoad++; 1730 1731 mSpnState = GetSpnFsmState.READ_SPN_3GPP; 1732 break; 1733 case READ_SPN_3GPP: 1734 if (ar != null && ar.exception == null) { 1735 data = (byte[]) ar.result; 1736 mSpnDisplayCondition = 0xff & data[0]; 1737 setServiceProviderName(IccUtils.adnStringFieldToString( 1738 data, 1, data.length - 1)); 1739 1740 if (DBG) log("Load EF_SPN: " + getServiceProviderName() 1741 + " spnDisplayCondition: " + mSpnDisplayCondition); 1742 mTelephonyManager.setSimOperatorNameForPhone( 1743 mParentApp.getPhoneId(), getServiceProviderName()); 1744 1745 mSpnState = GetSpnFsmState.IDLE; 1746 } else { 1747 mFh.loadEFTransparent( EF_SPN_CPHS, 1748 obtainMessage(EVENT_GET_SPN_DONE)); 1749 mRecordsToLoad++; 1750 1751 mSpnState = GetSpnFsmState.READ_SPN_CPHS; 1752 1753 // See TS 51.011 10.3.11. Basically, default to 1754 // show PLMN always, and SPN also if roaming. 1755 mSpnDisplayCondition = -1; 1756 } 1757 break; 1758 case READ_SPN_CPHS: 1759 if (ar != null && ar.exception == null) { 1760 data = (byte[]) ar.result; 1761 setServiceProviderName(IccUtils.adnStringFieldToString(data, 0, data.length)); 1762 1763 if (DBG) log("Load EF_SPN_CPHS: " + getServiceProviderName()); 1764 mTelephonyManager.setSimOperatorNameForPhone( 1765 mParentApp.getPhoneId(), getServiceProviderName()); 1766 1767 mSpnState = GetSpnFsmState.IDLE; 1768 } else { 1769 mFh.loadEFTransparent( 1770 EF_SPN_SHORT_CPHS, obtainMessage(EVENT_GET_SPN_DONE)); 1771 mRecordsToLoad++; 1772 1773 mSpnState = GetSpnFsmState.READ_SPN_SHORT_CPHS; 1774 } 1775 break; 1776 case READ_SPN_SHORT_CPHS: 1777 if (ar != null && ar.exception == null) { 1778 data = (byte[]) ar.result; 1779 setServiceProviderName(IccUtils.adnStringFieldToString(data, 0, data.length)); 1780 1781 if (DBG) log("Load EF_SPN_SHORT_CPHS: " + getServiceProviderName()); 1782 mTelephonyManager.setSimOperatorNameForPhone( 1783 mParentApp.getPhoneId(), getServiceProviderName()); 1784 }else { 1785 if (DBG) log("No SPN loaded in either CHPS or 3GPP"); 1786 } 1787 1788 mSpnState = GetSpnFsmState.IDLE; 1789 break; 1790 default: 1791 mSpnState = GetSpnFsmState.IDLE; 1792 } 1793 } 1794 1795 /** 1796 * Parse TS 51.011 EF[SPDI] record 1797 * This record contains the list of numeric network IDs that 1798 * are treated specially when determining SPN display 1799 */ 1800 private void 1801 parseEfSpdi(byte[] data) { 1802 SimTlv tlv = new SimTlv(data, 0, data.length); 1803 1804 byte[] plmnEntries = null; 1805 1806 for ( ; tlv.isValidObject() ; tlv.nextObject()) { 1807 // Skip SPDI tag, if existant 1808 if (tlv.getTag() == TAG_SPDI) { 1809 tlv = new SimTlv(tlv.getData(), 0, tlv.getData().length); 1810 } 1811 // There should only be one TAG_SPDI_PLMN_LIST 1812 if (tlv.getTag() == TAG_SPDI_PLMN_LIST) { 1813 plmnEntries = tlv.getData(); 1814 break; 1815 } 1816 } 1817 1818 if (plmnEntries == null) { 1819 return; 1820 } 1821 1822 mSpdiNetworks = new ArrayList<String>(plmnEntries.length / 3); 1823 1824 for (int i = 0 ; i + 2 < plmnEntries.length ; i += 3) { 1825 String plmnCode; 1826 plmnCode = IccUtils.bcdToString(plmnEntries, i, 3); 1827 1828 // Valid operator codes are 5 or 6 digits 1829 if (plmnCode.length() >= 5) { 1830 log("EF_SPDI network: " + plmnCode); 1831 mSpdiNetworks.add(plmnCode); 1832 } 1833 } 1834 } 1835 1836 /** 1837 * check to see if Mailbox Number is allocated and activated in CPHS SST 1838 */ 1839 private boolean isCphsMailboxEnabled() { 1840 if (mCphsInfo == null) return false; 1841 return ((mCphsInfo[1] & CPHS_SST_MBN_MASK) == CPHS_SST_MBN_ENABLED ); 1842 } 1843 1844 @Override 1845 protected void log(String s) { 1846 Rlog.d(LOG_TAG, "[SIMRecords] " + s); 1847 } 1848 1849 @Override 1850 protected void loge(String s) { 1851 Rlog.e(LOG_TAG, "[SIMRecords] " + s); 1852 } 1853 1854 protected void logw(String s, Throwable tr) { 1855 Rlog.w(LOG_TAG, "[SIMRecords] " + s, tr); 1856 } 1857 1858 protected void logv(String s) { 1859 Rlog.v(LOG_TAG, "[SIMRecords] " + s); 1860 } 1861 1862 /** 1863 * Return true if "Restriction of menu options for manual PLMN selection" 1864 * bit is set or EF_CSP data is unavailable, return false otherwise. 1865 */ 1866 @Override 1867 public boolean isCspPlmnEnabled() { 1868 return mCspPlmnEnabled; 1869 } 1870 1871 /** 1872 * Parse EF_CSP data and check if 1873 * "Restriction of menu options for manual PLMN selection" is 1874 * Enabled/Disabled 1875 * 1876 * @param data EF_CSP hex data. 1877 */ 1878 private void handleEfCspData(byte[] data) { 1879 // As per spec CPHS4_2.WW6, CPHS B.4.7.1, EF_CSP contains CPHS defined 1880 // 18 bytes (i.e 9 service groups info) and additional data specific to 1881 // operator. The valueAddedServicesGroup is not part of standard 1882 // services. This is operator specific and can be programmed any where. 1883 // Normally this is programmed as 10th service after the standard 1884 // services. 1885 int usedCspGroups = data.length / 2; 1886 // This is the "Service Group Number" of "Value Added Services Group". 1887 byte valueAddedServicesGroup = (byte)0xC0; 1888 1889 mCspPlmnEnabled = true; 1890 for (int i = 0; i < usedCspGroups; i++) { 1891 if (data[2 * i] == valueAddedServicesGroup) { 1892 log("[CSP] found ValueAddedServicesGroup, value " + data[(2 * i) + 1]); 1893 if ((data[(2 * i) + 1] & 0x80) == 0x80) { 1894 // Bit 8 is for 1895 // "Restriction of menu options for manual PLMN selection". 1896 // Operator Selection menu should be enabled. 1897 mCspPlmnEnabled = true; 1898 } else { 1899 mCspPlmnEnabled = false; 1900 // Operator Selection menu should be disabled. 1901 // Operator Selection Mode should be set to Automatic. 1902 log("[CSP] Set Automatic Network Selection"); 1903 mNetworkSelectionModeAutomaticRegistrants.notifyRegistrants(); 1904 } 1905 return; 1906 } 1907 } 1908 1909 log("[CSP] Value Added Service Group (0xC0), not found!"); 1910 } 1911 1912 @Override 1913 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1914 pw.println("SIMRecords: " + this); 1915 pw.println(" extends:"); 1916 super.dump(fd, pw, args); 1917 pw.println(" mVmConfig=" + mVmConfig); 1918 pw.println(" mSpnOverride=" + mSpnOverride); 1919 pw.println(" mCallForwardingEnabled=" + mCallForwardingEnabled); 1920 pw.println(" mSpnState=" + mSpnState); 1921 pw.println(" mCphsInfo=" + mCphsInfo); 1922 pw.println(" mCspPlmnEnabled=" + mCspPlmnEnabled); 1923 pw.println(" mEfMWIS[]=" + Arrays.toString(mEfMWIS)); 1924 pw.println(" mEfCPHS_MWI[]=" + Arrays.toString(mEfCPHS_MWI)); 1925 pw.println(" mEfCff[]=" + Arrays.toString(mEfCff)); 1926 pw.println(" mEfCfis[]=" + Arrays.toString(mEfCfis)); 1927 pw.println(" mSpnDisplayCondition=" + mSpnDisplayCondition); 1928 pw.println(" mSpdiNetworks[]=" + mSpdiNetworks); 1929 pw.println(" mPnnHomeName=" + mPnnHomeName); 1930 pw.println(" mUsimServiceTable=" + mUsimServiceTable); 1931 pw.println(" mGid1=" + mGid1); 1932 pw.println(" mGid2=" + mGid2); 1933 pw.flush(); 1934 } 1935} 1936