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