IccCardProxy.java revision 262aceca11c9cfeb910bc95765a17a801134d102
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.telephony.uicc; 18 19import static android.Manifest.permission.READ_PHONE_STATE; 20 21import android.app.ActivityManagerNative; 22import android.content.Context; 23import android.content.Intent; 24import android.os.AsyncResult; 25import android.os.Handler; 26import android.os.Message; 27import android.os.Registrant; 28import android.os.RegistrantList; 29import android.os.SystemProperties; 30import android.os.UserHandle; 31import android.telephony.Rlog; 32import android.telephony.ServiceState; 33import android.telephony.SubscriptionManager; 34import android.telephony.TelephonyManager; 35 36import com.android.internal.telephony.CommandsInterface; 37import com.android.internal.telephony.IccCard; 38import com.android.internal.telephony.IccCardConstants; 39import com.android.internal.telephony.PhoneConstants; 40import com.android.internal.telephony.MccTable; 41import com.android.internal.telephony.RILConstants; 42import com.android.internal.telephony.TelephonyIntents; 43import com.android.internal.telephony.IccCardConstants.State; 44import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 45import com.android.internal.telephony.Phone; 46import com.android.internal.telephony.SubscriptionController; 47import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 48import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState; 49import com.android.internal.telephony.uicc.IccCardStatus.CardState; 50import com.android.internal.telephony.uicc.IccCardStatus.PinState; 51import com.android.internal.telephony.uicc.UiccController; 52 53import java.io.FileDescriptor; 54import java.io.PrintWriter; 55 56import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; 57import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; 58import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; 59import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_STATE; 60 61 62/** 63 * @Deprecated use {@link UiccController}.getUiccCard instead. 64 * 65 * The Phone App assumes that there is only one icc card, and one icc application 66 * available at a time. Moreover, it assumes such object (represented with IccCard) 67 * is available all the time (whether {@link RILConstants#RIL_REQUEST_GET_SIM_STATUS} returned 68 * or not, whether card has desired application or not, whether there really is a card in the 69 * slot or not). 70 * 71 * UiccController, however, can handle multiple instances of icc objects (multiple 72 * {@link UiccCardApplication}, multiple {@link IccFileHandler}, multiple {@link IccRecords}) 73 * created and destroyed dynamically during phone operation. 74 * 75 * This class implements the IccCard interface that is always available (right after default 76 * phone object is constructed) to expose the current (based on voice radio technology) 77 * application on the uicc card, so that external apps won't break. 78 */ 79 80public class IccCardProxy extends Handler implements IccCard { 81 private static final boolean DBG = true; 82 private static final String LOG_TAG = "IccCardProxy"; 83 84 private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 1; 85 private static final int EVENT_RADIO_ON = 2; 86 private static final int EVENT_ICC_CHANGED = 3; 87 private static final int EVENT_ICC_ABSENT = 4; 88 private static final int EVENT_ICC_LOCKED = 5; 89 private static final int EVENT_APP_READY = 6; 90 private static final int EVENT_RECORDS_LOADED = 7; 91 private static final int EVENT_IMSI_READY = 8; 92 private static final int EVENT_NETWORK_LOCKED = 9; 93 private static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 11; 94 95 private static final int EVENT_ICC_RECORD_EVENTS = 500; 96 private static final int EVENT_SUBSCRIPTION_ACTIVATED = 501; 97 private static final int EVENT_SUBSCRIPTION_DEACTIVATED = 502; 98 private static final int EVENT_CARRIER_PRIVILIGES_LOADED = 503; 99 100 private Integer mPhoneId = null; 101 102 private final Object mLock = new Object(); 103 private Context mContext; 104 private CommandsInterface mCi; 105 106 private RegistrantList mAbsentRegistrants = new RegistrantList(); 107 private RegistrantList mPinLockedRegistrants = new RegistrantList(); 108 private RegistrantList mNetworkLockedRegistrants = new RegistrantList(); 109 110 private int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp? 111 private UiccController mUiccController = null; 112 private UiccCard mUiccCard = null; 113 private UiccCardApplication mUiccApplication = null; 114 private IccRecords mIccRecords = null; 115 private CdmaSubscriptionSourceManager mCdmaSSM = null; 116 private boolean mRadioOn = false; 117 private boolean mQuietMode = false; // when set to true IccCardProxy will not broadcast 118 // ACTION_SIM_STATE_CHANGED intents 119 private boolean mInitialized = false; 120 private State mExternalState = State.UNKNOWN; 121 122 public static final String ACTION_INTERNAL_SIM_STATE_CHANGED = "android.intent.action.internal_sim_state_changed"; 123 124 public IccCardProxy(Context context, CommandsInterface ci, int phoneId) { 125 if (DBG) log("ctor: ci=" + ci + " phoneId=" + phoneId); 126 mContext = context; 127 mCi = ci; 128 mPhoneId = phoneId; 129 mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, 130 ci, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); 131 mUiccController = UiccController.getInstance(); 132 mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null); 133 ci.registerForOn(this,EVENT_RADIO_ON, null); 134 ci.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_UNAVAILABLE, null); 135 136 resetProperties(); 137 setExternalState(State.NOT_READY, false); 138 } 139 140 public void dispose() { 141 synchronized (mLock) { 142 log("Disposing"); 143 //Cleanup icc references 144 mUiccController.unregisterForIccChanged(this); 145 mUiccController = null; 146 mCi.unregisterForOn(this); 147 mCi.unregisterForOffOrNotAvailable(this); 148 mCdmaSSM.dispose(this); 149 } 150 } 151 152 /* 153 * The card application that the external world sees will be based on the 154 * voice radio technology only! 155 */ 156 public void setVoiceRadioTech(int radioTech) { 157 synchronized (mLock) { 158 if (DBG) { 159 log("Setting radio tech " + ServiceState.rilRadioTechnologyToString(radioTech)); 160 } 161 if (ServiceState.isGsm(radioTech)) { 162 mCurrentAppType = UiccController.APP_FAM_3GPP; 163 } else { 164 mCurrentAppType = UiccController.APP_FAM_3GPP2; 165 } 166 updateQuietMode(); 167 } 168 } 169 170 /** 171 * In case of 3gpp2 we need to find out if subscription used is coming from 172 * NV in which case we shouldn't broadcast any sim states changes. 173 */ 174 private void updateQuietMode() { 175 synchronized (mLock) { 176 boolean oldQuietMode = mQuietMode; 177 boolean newQuietMode; 178 int cdmaSource = Phone.CDMA_SUBSCRIPTION_UNKNOWN; 179 boolean isLteOnCdmaMode = TelephonyManager.getLteOnCdmaModeStatic() 180 == PhoneConstants.LTE_ON_CDMA_TRUE; 181 if (mCurrentAppType == UiccController.APP_FAM_3GPP) { 182 newQuietMode = false; 183 if (DBG) log("updateQuietMode: 3GPP subscription -> newQuietMode=" + newQuietMode); 184 } else { 185 if (isLteOnCdmaMode) { 186 log("updateQuietMode: is cdma/lte device, force IccCardProxy into 3gpp mode"); 187 mCurrentAppType = UiccController.APP_FAM_3GPP; 188 } 189 cdmaSource = mCdmaSSM != null ? 190 mCdmaSSM.getCdmaSubscriptionSource() : Phone.CDMA_SUBSCRIPTION_UNKNOWN; 191 192 newQuietMode = (cdmaSource == Phone.CDMA_SUBSCRIPTION_NV) 193 && (mCurrentAppType == UiccController.APP_FAM_3GPP2) 194 && !isLteOnCdmaMode; 195 if (DBG) { 196 log("updateQuietMode: cdmaSource=" + cdmaSource 197 + " mCurrentAppType=" + mCurrentAppType 198 + " isLteOnCdmaMode=" + isLteOnCdmaMode 199 + " newQuietMode=" + newQuietMode); 200 } 201 } 202 203 if (mQuietMode == false && newQuietMode == true) { 204 // Last thing to do before switching to quiet mode is 205 // broadcast ICC_READY 206 log("Switching to QuietMode."); 207 setExternalState(State.READY); 208 mQuietMode = newQuietMode; 209 } else if (mQuietMode == true && newQuietMode == false) { 210 if (DBG) { 211 log("updateQuietMode: Switching out from QuietMode." 212 + " Force broadcast of current state=" + mExternalState); 213 } 214 mQuietMode = newQuietMode; 215 setExternalState(mExternalState, true); 216 } else { 217 if (DBG) log("updateQuietMode: no changes don't setExternalState"); 218 } 219 if (DBG) { 220 log("updateQuietMode: QuietMode is " + mQuietMode + " (app_type=" 221 + mCurrentAppType + " isLteOnCdmaMode=" + isLteOnCdmaMode 222 + " cdmaSource=" + cdmaSource + ")"); 223 } 224 mInitialized = true; 225 sendMessage(obtainMessage(EVENT_ICC_CHANGED)); 226 } 227 } 228 229 @Override 230 public void handleMessage(Message msg) { 231 switch (msg.what) { 232 case EVENT_RADIO_OFF_OR_UNAVAILABLE: 233 mRadioOn = false; 234 if (CommandsInterface.RadioState.RADIO_UNAVAILABLE == mCi.getRadioState()) { 235 setExternalState(State.NOT_READY); 236 } 237 break; 238 case EVENT_RADIO_ON: 239 mRadioOn = true; 240 if (!mInitialized) { 241 updateQuietMode(); 242 } 243 break; 244 case EVENT_ICC_CHANGED: 245 if (mInitialized) { 246 updateIccAvailability(); 247 } 248 break; 249 case EVENT_ICC_ABSENT: 250 mAbsentRegistrants.notifyRegistrants(); 251 setExternalState(State.ABSENT); 252 break; 253 case EVENT_ICC_LOCKED: 254 processLockedState(); 255 break; 256 case EVENT_APP_READY: 257 setExternalState(State.READY); 258 break; 259 case EVENT_RECORDS_LOADED: 260 // Update the MCC/MNC. 261 if (mIccRecords != null) { 262 String operator = mIccRecords.getOperatorNumeric(); 263 log("operator=" + operator + " mPhoneId=" + mPhoneId); 264 265 if (operator != null) { 266 log("update icc_operator_numeric=" + operator); 267 setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operator); 268 String countryCode = operator.substring(0,3); 269 if (countryCode != null) { 270 setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, 271 MccTable.countryCodeForMcc(Integer.parseInt(countryCode))); 272 } else { 273 loge("EVENT_RECORDS_LOADED Country code is null"); 274 } 275 } else { 276 loge("EVENT_RECORDS_LOADED Operator name is null"); 277 } 278 } 279 if (mUiccCard != null && !mUiccCard.areCarrierPriviligeRulesLoaded()) { 280 mUiccCard.registerForCarrierPrivilegeRulesLoaded( 281 this, EVENT_CARRIER_PRIVILIGES_LOADED, null); 282 } else { 283 onRecordsLoaded(); 284 } 285 break; 286 case EVENT_IMSI_READY: 287 broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_IMSI, null); 288 break; 289 case EVENT_NETWORK_LOCKED: 290 mNetworkLockedRegistrants.notifyRegistrants(); 291 setExternalState(State.NETWORK_LOCKED); 292 break; 293 case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED: 294 updateQuietMode(); 295 break; 296 case EVENT_SUBSCRIPTION_ACTIVATED: 297 log("EVENT_SUBSCRIPTION_ACTIVATED"); 298 onSubscriptionActivated(); 299 break; 300 301 case EVENT_SUBSCRIPTION_DEACTIVATED: 302 log("EVENT_SUBSCRIPTION_DEACTIVATED"); 303 onSubscriptionDeactivated(); 304 break; 305 306 case EVENT_ICC_RECORD_EVENTS: 307 if ((mCurrentAppType == UiccController.APP_FAM_3GPP) && (mIccRecords != null)) { 308 AsyncResult ar = (AsyncResult)msg.obj; 309 int eventCode = (Integer) ar.result; 310 if (eventCode == SIMRecords.EVENT_SPN) { 311 setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, 312 mIccRecords.getServiceProviderName()); 313 } 314 } 315 break; 316 317 case EVENT_CARRIER_PRIVILIGES_LOADED: 318 log("EVENT_CARRIER_PRIVILEGES_LOADED"); 319 if (mUiccCard != null) { 320 mUiccCard.unregisterForCarrierPrivilegeRulesLoaded(this); 321 } 322 onRecordsLoaded(); 323 break; 324 325 default: 326 loge("Unhandled message with number: " + msg.what); 327 break; 328 } 329 } 330 331 private void onSubscriptionActivated() { 332 updateIccAvailability(); 333 updateStateProperty(); 334 } 335 336 private void onSubscriptionDeactivated() { 337 resetProperties(); 338 updateIccAvailability(); 339 updateStateProperty(); 340 } 341 342 private void onRecordsLoaded() { 343 broadcastInternalIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null); 344 } 345 346 private void updateIccAvailability() { 347 synchronized (mLock) { 348 UiccCard newCard = mUiccController.getUiccCard(mPhoneId); 349 CardState state = CardState.CARDSTATE_ABSENT; 350 UiccCardApplication newApp = null; 351 IccRecords newRecords = null; 352 if (newCard != null) { 353 state = newCard.getCardState(); 354 newApp = newCard.getApplication(mCurrentAppType); 355 if (newApp != null) { 356 newRecords = newApp.getIccRecords(); 357 } 358 } 359 360 if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) { 361 if (DBG) log("Icc changed. Reregestering."); 362 unregisterUiccCardEvents(); 363 mUiccCard = newCard; 364 mUiccApplication = newApp; 365 mIccRecords = newRecords; 366 registerUiccCardEvents(); 367 } 368 369 updateExternalState(); 370 } 371 } 372 373 void resetProperties() { 374 if (mCurrentAppType == UiccController.APP_FAM_3GPP) { 375 log("update icc_operator_numeric=" + ""); 376 setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, ""); 377 setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, ""); 378 setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, ""); 379 } 380 } 381 382 private void HandleDetectedState() { 383 // CAF_MSIM SAND 384// setExternalState(State.DETECTED, false); 385 } 386 387 private void updateExternalState() { 388 if (mUiccCard == null || mUiccCard.getCardState() == CardState.CARDSTATE_ABSENT) { 389 if (mRadioOn) { 390 setExternalState(State.ABSENT); 391 } else { 392 setExternalState(State.NOT_READY); 393 } 394 return; 395 } 396 397 if (mUiccCard.getCardState() == CardState.CARDSTATE_ERROR) { 398 setExternalState(State.CARD_IO_ERROR); 399 return; 400 } 401 402 if (mUiccApplication == null) { 403 setExternalState(State.NOT_READY); 404 return; 405 } 406 407 switch (mUiccApplication.getState()) { 408 case APPSTATE_UNKNOWN: 409 setExternalState(State.UNKNOWN); 410 break; 411 case APPSTATE_DETECTED: 412 HandleDetectedState(); 413 break; 414 case APPSTATE_PIN: 415 setExternalState(State.PIN_REQUIRED); 416 break; 417 case APPSTATE_PUK: 418 setExternalState(State.PUK_REQUIRED); 419 break; 420 case APPSTATE_SUBSCRIPTION_PERSO: 421 if (mUiccApplication.getPersoSubState() == 422 PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 423 setExternalState(State.NETWORK_LOCKED); 424 } else { 425 setExternalState(State.UNKNOWN); 426 } 427 break; 428 case APPSTATE_READY: 429 setExternalState(State.READY); 430 break; 431 } 432 } 433 434 private void registerUiccCardEvents() { 435 if (mUiccCard != null) { 436 mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null); 437 } 438 if (mUiccApplication != null) { 439 mUiccApplication.registerForReady(this, EVENT_APP_READY, null); 440 mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null); 441 mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null); 442 } 443 if (mIccRecords != null) { 444 mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null); 445 mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null); 446 mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); 447 } 448 } 449 450 private void unregisterUiccCardEvents() { 451 if (mUiccCard != null) mUiccCard.unregisterForAbsent(this); 452 if (mUiccApplication != null) mUiccApplication.unregisterForReady(this); 453 if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this); 454 if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this); 455 if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this); 456 if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this); 457 if (mIccRecords != null) mIccRecords.unregisterForRecordsEvents(this); 458 } 459 460 private void updateStateProperty() { 461 setSystemProperty(PROPERTY_SIM_STATE, getState().toString()); 462 } 463 464 private void broadcastIccStateChangedIntent(String value, String reason) { 465 synchronized (mLock) { 466 if (mPhoneId == null || !SubscriptionManager.isValidSlotId(mPhoneId)) { 467 loge("broadcastIccStateChangedIntent: mPhoneId=" + mPhoneId 468 + " is invalid; Return!!"); 469 return; 470 } 471 472 if (mQuietMode) { 473 log("broadcastIccStateChangedIntent: QuietMode" 474 + " NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " 475 + " value=" + value + " reason=" + reason); 476 return; 477 } 478 479 Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 480 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 481 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 482 intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 483 intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value); 484 intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 485 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhoneId); 486 log("broadcastIccStateChangedIntent intent ACTION_SIM_STATE_CHANGED value=" + value 487 + " reason=" + reason + " for mPhoneId=" + mPhoneId); 488 ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE, 489 UserHandle.USER_ALL); 490 } 491 } 492 493 private void broadcastInternalIccStateChangedIntent(String value, String reason) { 494 synchronized (mLock) { 495 if (mPhoneId == null) { 496 loge("broadcastInternalIccStateChangedIntent: Card Index is not set; Return!!"); 497 return; 498 } 499 500 Intent intent = new Intent(ACTION_INTERNAL_SIM_STATE_CHANGED); 501 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 502 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 503 intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 504 intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value); 505 intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 506 intent.putExtra(PhoneConstants.PHONE_KEY, mPhoneId); // SubId may not be valid. 507 log("Sending intent ACTION_INTERNAL_SIM_STATE_CHANGED" + " for mPhoneId : " + mPhoneId); 508 ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 509 } 510 } 511 512 private void setExternalState(State newState, boolean override) { 513 synchronized (mLock) { 514 if (mPhoneId == null || !SubscriptionManager.isValidSlotId(mPhoneId)) { 515 loge("setExternalState: mPhoneId=" + mPhoneId + " is invalid; Return!!"); 516 return; 517 } 518 519 if (!override && newState == mExternalState) { 520 loge("setExternalState: !override and newstate unchanged from " + newState); 521 return; 522 } 523 mExternalState = newState; 524 loge("setExternalState: set mPhoneId=" + mPhoneId + " mExternalState=" + mExternalState); 525 setSystemProperty(PROPERTY_SIM_STATE, getState().toString()); 526 527 // For locked states, we should be sending internal broadcast. 528 if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(getIccStateIntentString(mExternalState))) { 529 broadcastInternalIccStateChangedIntent(getIccStateIntentString(mExternalState), 530 getIccStateReason(mExternalState)); 531 } else { 532 broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState), 533 getIccStateReason(mExternalState)); 534 } 535 // TODO: Need to notify registrants for other states as well. 536 if ( State.ABSENT == mExternalState) { 537 mAbsentRegistrants.notifyRegistrants(); 538 } 539 } 540 } 541 542 private void processLockedState() { 543 synchronized (mLock) { 544 if (mUiccApplication == null) { 545 //Don't need to do anything if non-existent application is locked 546 return; 547 } 548 PinState pin1State = mUiccApplication.getPin1State(); 549 if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) { 550 setExternalState(State.PERM_DISABLED); 551 return; 552 } 553 554 AppState appState = mUiccApplication.getState(); 555 switch (appState) { 556 case APPSTATE_PIN: 557 mPinLockedRegistrants.notifyRegistrants(); 558 setExternalState(State.PIN_REQUIRED); 559 break; 560 case APPSTATE_PUK: 561 setExternalState(State.PUK_REQUIRED); 562 break; 563 case APPSTATE_DETECTED: 564 case APPSTATE_READY: 565 case APPSTATE_SUBSCRIPTION_PERSO: 566 case APPSTATE_UNKNOWN: 567 // Neither required 568 break; 569 } 570 } 571 } 572 573 private void setExternalState(State newState) { 574 setExternalState(newState, false); 575 } 576 577 public boolean getIccRecordsLoaded() { 578 synchronized (mLock) { 579 if (mIccRecords != null) { 580 return mIccRecords.getRecordsLoaded(); 581 } 582 return false; 583 } 584 } 585 586 private String getIccStateIntentString(State state) { 587 switch (state) { 588 case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT; 589 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 590 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 591 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 592 case READY: return IccCardConstants.INTENT_VALUE_ICC_READY; 593 case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY; 594 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 595 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 596 default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN; 597 } 598 } 599 600 /** 601 * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED, CARD_IO_ERROR) 602 * @return reason 603 */ 604 private String getIccStateReason(State state) { 605 switch (state) { 606 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN; 607 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK; 608 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK; 609 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED; 610 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 611 default: return null; 612 } 613 } 614 615 /* IccCard interface implementation */ 616 @Override 617 public State getState() { 618 synchronized (mLock) { 619 return mExternalState; 620 } 621 } 622 623 @Override 624 public IccRecords getIccRecords() { 625 synchronized (mLock) { 626 return mIccRecords; 627 } 628 } 629 630 @Override 631 public IccFileHandler getIccFileHandler() { 632 synchronized (mLock) { 633 if (mUiccApplication != null) { 634 return mUiccApplication.getIccFileHandler(); 635 } 636 return null; 637 } 638 } 639 640 /** 641 * Notifies handler of any transition into State.ABSENT 642 */ 643 @Override 644 public void registerForAbsent(Handler h, int what, Object obj) { 645 synchronized (mLock) { 646 Registrant r = new Registrant (h, what, obj); 647 648 mAbsentRegistrants.add(r); 649 650 if (getState() == State.ABSENT) { 651 r.notifyRegistrant(); 652 } 653 } 654 } 655 656 @Override 657 public void unregisterForAbsent(Handler h) { 658 synchronized (mLock) { 659 mAbsentRegistrants.remove(h); 660 } 661 } 662 663 /** 664 * Notifies handler of any transition into State.NETWORK_LOCKED 665 */ 666 @Override 667 public void registerForNetworkLocked(Handler h, int what, Object obj) { 668 synchronized (mLock) { 669 Registrant r = new Registrant (h, what, obj); 670 671 mNetworkLockedRegistrants.add(r); 672 673 if (getState() == State.NETWORK_LOCKED) { 674 r.notifyRegistrant(); 675 } 676 } 677 } 678 679 @Override 680 public void unregisterForNetworkLocked(Handler h) { 681 synchronized (mLock) { 682 mNetworkLockedRegistrants.remove(h); 683 } 684 } 685 686 /** 687 * Notifies handler of any transition into State.isPinLocked() 688 */ 689 @Override 690 public void registerForLocked(Handler h, int what, Object obj) { 691 synchronized (mLock) { 692 Registrant r = new Registrant (h, what, obj); 693 694 mPinLockedRegistrants.add(r); 695 696 if (getState().isPinLocked()) { 697 r.notifyRegistrant(); 698 } 699 } 700 } 701 702 @Override 703 public void unregisterForLocked(Handler h) { 704 synchronized (mLock) { 705 mPinLockedRegistrants.remove(h); 706 } 707 } 708 709 @Override 710 public void supplyPin(String pin, Message onComplete) { 711 synchronized (mLock) { 712 if (mUiccApplication != null) { 713 mUiccApplication.supplyPin(pin, onComplete); 714 } else if (onComplete != null) { 715 Exception e = new RuntimeException("ICC card is absent."); 716 AsyncResult.forMessage(onComplete).exception = e; 717 onComplete.sendToTarget(); 718 return; 719 } 720 } 721 } 722 723 @Override 724 public void supplyPuk(String puk, String newPin, Message onComplete) { 725 synchronized (mLock) { 726 if (mUiccApplication != null) { 727 mUiccApplication.supplyPuk(puk, newPin, onComplete); 728 } else if (onComplete != null) { 729 Exception e = new RuntimeException("ICC card is absent."); 730 AsyncResult.forMessage(onComplete).exception = e; 731 onComplete.sendToTarget(); 732 return; 733 } 734 } 735 } 736 737 @Override 738 public void supplyPin2(String pin2, Message onComplete) { 739 synchronized (mLock) { 740 if (mUiccApplication != null) { 741 mUiccApplication.supplyPin2(pin2, onComplete); 742 } else if (onComplete != null) { 743 Exception e = new RuntimeException("ICC card is absent."); 744 AsyncResult.forMessage(onComplete).exception = e; 745 onComplete.sendToTarget(); 746 return; 747 } 748 } 749 } 750 751 @Override 752 public void supplyPuk2(String puk2, String newPin2, Message onComplete) { 753 synchronized (mLock) { 754 if (mUiccApplication != null) { 755 mUiccApplication.supplyPuk2(puk2, newPin2, onComplete); 756 } else if (onComplete != null) { 757 Exception e = new RuntimeException("ICC card is absent."); 758 AsyncResult.forMessage(onComplete).exception = e; 759 onComplete.sendToTarget(); 760 return; 761 } 762 } 763 } 764 765 @Override 766 public void supplyNetworkDepersonalization(String pin, Message onComplete) { 767 synchronized (mLock) { 768 if (mUiccApplication != null) { 769 mUiccApplication.supplyNetworkDepersonalization(pin, onComplete); 770 } else if (onComplete != null) { 771 Exception e = new RuntimeException("CommandsInterface is not set."); 772 AsyncResult.forMessage(onComplete).exception = e; 773 onComplete.sendToTarget(); 774 return; 775 } 776 } 777 } 778 779 @Override 780 public boolean getIccLockEnabled() { 781 synchronized (mLock) { 782 /* defaults to false, if ICC is absent/deactivated */ 783 Boolean retValue = mUiccApplication != null ? 784 mUiccApplication.getIccLockEnabled() : false; 785 return retValue; 786 } 787 } 788 789 @Override 790 public boolean getIccFdnEnabled() { 791 synchronized (mLock) { 792 Boolean retValue = mUiccApplication != null ? 793 mUiccApplication.getIccFdnEnabled() : false; 794 return retValue; 795 } 796 } 797 798 public boolean getIccFdnAvailable() { 799 boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnAvailable() : false; 800 return retValue; 801 } 802 803 public boolean getIccPin2Blocked() { 804 /* defaults to disabled */ 805 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPin2Blocked() : false; 806 return retValue; 807 } 808 809 public boolean getIccPuk2Blocked() { 810 /* defaults to disabled */ 811 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPuk2Blocked() : false; 812 return retValue; 813 } 814 815 @Override 816 public void setIccLockEnabled(boolean enabled, String password, Message onComplete) { 817 synchronized (mLock) { 818 if (mUiccApplication != null) { 819 mUiccApplication.setIccLockEnabled(enabled, password, onComplete); 820 } else if (onComplete != null) { 821 Exception e = new RuntimeException("ICC card is absent."); 822 AsyncResult.forMessage(onComplete).exception = e; 823 onComplete.sendToTarget(); 824 return; 825 } 826 } 827 } 828 829 @Override 830 public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) { 831 synchronized (mLock) { 832 if (mUiccApplication != null) { 833 mUiccApplication.setIccFdnEnabled(enabled, password, onComplete); 834 } else if (onComplete != null) { 835 Exception e = new RuntimeException("ICC card is absent."); 836 AsyncResult.forMessage(onComplete).exception = e; 837 onComplete.sendToTarget(); 838 return; 839 } 840 } 841 } 842 843 @Override 844 public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) { 845 synchronized (mLock) { 846 if (mUiccApplication != null) { 847 mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete); 848 } else if (onComplete != null) { 849 Exception e = new RuntimeException("ICC card is absent."); 850 AsyncResult.forMessage(onComplete).exception = e; 851 onComplete.sendToTarget(); 852 return; 853 } 854 } 855 } 856 857 @Override 858 public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) { 859 synchronized (mLock) { 860 if (mUiccApplication != null) { 861 mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete); 862 } else if (onComplete != null) { 863 Exception e = new RuntimeException("ICC card is absent."); 864 AsyncResult.forMessage(onComplete).exception = e; 865 onComplete.sendToTarget(); 866 return; 867 } 868 } 869 } 870 871 @Override 872 public String getServiceProviderName() { 873 synchronized (mLock) { 874 if (mIccRecords != null) { 875 return mIccRecords.getServiceProviderName(); 876 } 877 return null; 878 } 879 } 880 881 @Override 882 public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) { 883 synchronized (mLock) { 884 Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false; 885 return retValue; 886 } 887 } 888 889 @Override 890 public boolean hasIccCard() { 891 synchronized (mLock) { 892 if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) { 893 return true; 894 } 895 return false; 896 } 897 } 898 899 private void setSystemProperty(String property, String value) { 900 TelephonyManager.setTelephonyProperty(mPhoneId, property, value); 901 } 902 903 public IccRecords getIccRecord() { 904 return mIccRecords; 905 } 906 private void log(String s) { 907 Rlog.d(LOG_TAG, s); 908 } 909 910 private void loge(String msg) { 911 Rlog.e(LOG_TAG, msg); 912 } 913 914 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 915 pw.println("IccCardProxy: " + this); 916 pw.println(" mContext=" + mContext); 917 pw.println(" mCi=" + mCi); 918 pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size()); 919 for (int i = 0; i < mAbsentRegistrants.size(); i++) { 920 pw.println(" mAbsentRegistrants[" + i + "]=" 921 + ((Registrant)mAbsentRegistrants.get(i)).getHandler()); 922 } 923 pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size()); 924 for (int i = 0; i < mPinLockedRegistrants.size(); i++) { 925 pw.println(" mPinLockedRegistrants[" + i + "]=" 926 + ((Registrant)mPinLockedRegistrants.get(i)).getHandler()); 927 } 928 pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size()); 929 for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) { 930 pw.println(" mNetworkLockedRegistrants[" + i + "]=" 931 + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler()); 932 } 933 pw.println(" mCurrentAppType=" + mCurrentAppType); 934 pw.println(" mUiccController=" + mUiccController); 935 pw.println(" mUiccCard=" + mUiccCard); 936 pw.println(" mUiccApplication=" + mUiccApplication); 937 pw.println(" mIccRecords=" + mIccRecords); 938 pw.println(" mCdmaSSM=" + mCdmaSSM); 939 pw.println(" mRadioOn=" + mRadioOn); 940 pw.println(" mQuietMode=" + mQuietMode); 941 pw.println(" mInitialized=" + mInitialized); 942 pw.println(" mExternalState=" + mExternalState); 943 944 pw.flush(); 945 } 946} 947