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