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