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