IccCardProxy.java revision 47b83a09b03fe159a0cc7f7a60f9120a9fb4fca7
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 // FIXME Rename mCardIndex to mSlotId. 101 private Integer mCardIndex = null; 102 103 private final Object mLock = new Object(); 104 private Context mContext; 105 private CommandsInterface mCi; 106 107 private RegistrantList mAbsentRegistrants = new RegistrantList(); 108 private RegistrantList mPinLockedRegistrants = new RegistrantList(); 109 private RegistrantList mNetworkLockedRegistrants = new RegistrantList(); 110 111 private int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp? 112 private UiccController mUiccController = null; 113 private UiccCard mUiccCard = null; 114 private UiccCardApplication mUiccApplication = null; 115 private IccRecords mIccRecords = null; 116 private CdmaSubscriptionSourceManager mCdmaSSM = null; 117 private boolean mRadioOn = false; 118 private boolean mQuietMode = false; // when set to true IccCardProxy will not broadcast 119 // ACTION_SIM_STATE_CHANGED intents 120 private boolean mInitialized = false; 121 private State mExternalState = State.UNKNOWN; 122 123 private int mRecordsToLoad; // number of pending load requests 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 onRecordsLoaded(); 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 int slotId = mCardIndex; 309 AsyncResult ar = (AsyncResult)msg.obj; 310 int eventCode = (Integer) ar.result; 311 if (eventCode == SIMRecords.EVENT_SPN) { 312 setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, slotId, 313 mIccRecords.getServiceProviderName()); 314 } 315 } 316 break; 317 318 case EVENT_CARRIER_PRIVILIGES_LOADED: 319 log("EVENT_CARRIER_PRIVILEGES_LOADED"); 320 onRecordsLoaded(); 321 break; 322 323 default: 324 loge("Unhandled message with number: " + msg.what); 325 break; 326 } 327 } 328 329 private void onSubscriptionActivated() { 330 updateIccAvailability(); 331 updateStateProperty(); 332 } 333 334 private void onSubscriptionDeactivated() { 335 resetProperties(); 336 updateIccAvailability(); 337 updateStateProperty(); 338 } 339 340 private void onRecordsLoaded() { 341 synchronized (mLock) { 342 --mRecordsToLoad; 343 if (mRecordsToLoad == 0) { 344 broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null); 345 } 346 } 347 } 348 349 private void updateIccAvailability() { 350 synchronized (mLock) { 351 UiccCard newCard = mUiccController.getUiccCard(mCardIndex); 352 CardState state = CardState.CARDSTATE_ABSENT; 353 UiccCardApplication newApp = null; 354 IccRecords newRecords = null; 355 if (newCard != null) { 356 state = newCard.getCardState(); 357 newApp = newCard.getApplication(mCurrentAppType); 358 if (newApp != null) { 359 newRecords = newApp.getIccRecords(); 360 } 361 } 362 363 if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) { 364 if (DBG) log("Icc changed. Reregestering."); 365 mRecordsToLoad = 0; 366 unregisterUiccCardEvents(); 367 mUiccCard = newCard; 368 mUiccApplication = newApp; 369 mIccRecords = newRecords; 370 registerUiccCardEvents(); 371 } 372 373 updateExternalState(); 374 } 375 } 376 377 void resetProperties() { 378 if (mCurrentAppType == UiccController.APP_FAM_3GPP) { 379 log("update icc_operator_numeric=" + ""); 380 setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, mCardIndex, ""); 381 setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, mCardIndex, ""); 382 setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, mCardIndex, ""); 383 } 384 } 385 386 private void HandleDetectedState() { 387 // CAF_MSIM SAND 388// setExternalState(State.DETECTED, false); 389 } 390 391 private void updateExternalState() { 392 if (mUiccCard == null || mUiccCard.getCardState() == CardState.CARDSTATE_ABSENT) { 393 if (mRadioOn) { 394 setExternalState(State.ABSENT); 395 } else { 396 setExternalState(State.NOT_READY); 397 } 398 return; 399 } 400 401 if (mUiccCard.getCardState() == CardState.CARDSTATE_ERROR) { 402 setExternalState(State.CARD_IO_ERROR); 403 return; 404 } 405 406 if (mUiccApplication == null) { 407 setExternalState(State.NOT_READY); 408 return; 409 } 410 411 switch (mUiccApplication.getState()) { 412 case APPSTATE_UNKNOWN: 413 setExternalState(State.UNKNOWN); 414 break; 415 case APPSTATE_DETECTED: 416 HandleDetectedState(); 417 break; 418 case APPSTATE_PIN: 419 setExternalState(State.PIN_REQUIRED); 420 break; 421 case APPSTATE_PUK: 422 setExternalState(State.PUK_REQUIRED); 423 break; 424 case APPSTATE_SUBSCRIPTION_PERSO: 425 if (mUiccApplication.getPersoSubState() == 426 PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 427 setExternalState(State.NETWORK_LOCKED); 428 } else { 429 setExternalState(State.UNKNOWN); 430 } 431 break; 432 case APPSTATE_READY: 433 setExternalState(State.READY); 434 break; 435 } 436 } 437 438 private void registerUiccCardEvents() { 439 mRecordsToLoad = (mUiccCard != null ? 1 : 0) + 440 (mIccRecords != null ? 1 : 0); 441 442 if (mUiccCard != null) { 443 mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null); 444 mUiccCard.registerForCarrierPrivilegeRulesLoaded( 445 this, EVENT_CARRIER_PRIVILIGES_LOADED, 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 (mUiccCard != null) mUiccCard.unregisterForCarrierPrivilegeRulesLoaded(this); 462 if (mUiccApplication != null) mUiccApplication.unregisterForReady(this); 463 if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this); 464 if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this); 465 if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this); 466 if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this); 467 if (mIccRecords != null) mIccRecords.unregisterForRecordsEvents(this); 468 } 469 470 private void updateStateProperty() { 471 setSystemProperty(PROPERTY_SIM_STATE, mCardIndex,getState().toString()); 472 } 473 474 private void broadcastIccStateChangedIntent(String value, String reason) { 475 synchronized (mLock) { 476 if (mCardIndex == null) { 477 loge("broadcastIccStateChangedIntent: Card Index is not set; Return!!"); 478 return; 479 } 480 481 if (mQuietMode) { 482 log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " + value 483 + " reason " + reason); 484 return; 485 } 486 487 Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 488 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 489 intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 490 intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value); 491 intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 492 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mCardIndex); 493 log("Broadcasting intent ACTION_SIM_STATE_CHANGED " + value 494 + " reason " + reason + " for mCardIndex : " + mCardIndex); 495 ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE, 496 UserHandle.USER_ALL); 497 } 498 } 499 500 private void setExternalState(State newState, boolean override) { 501 synchronized (mLock) { 502 if (mCardIndex == null) { 503 loge("setExternalState: Card Index is not set; Return!!"); 504 return; 505 } 506 507 if (!override && newState == mExternalState) { 508 return; 509 } 510 mExternalState = newState; 511 setSystemProperty(PROPERTY_SIM_STATE, mCardIndex, getState().toString()); 512 broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState), 513 getIccStateReason(mExternalState)); 514 // TODO: Need to notify registrants for other states as well. 515 if ( State.ABSENT == mExternalState) { 516 mAbsentRegistrants.notifyRegistrants(); 517 } 518 } 519 } 520 521 private void processLockedState() { 522 synchronized (mLock) { 523 if (mUiccApplication == null) { 524 //Don't need to do anything if non-existent application is locked 525 return; 526 } 527 PinState pin1State = mUiccApplication.getPin1State(); 528 if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) { 529 setExternalState(State.PERM_DISABLED); 530 return; 531 } 532 533 AppState appState = mUiccApplication.getState(); 534 switch (appState) { 535 case APPSTATE_PIN: 536 mPinLockedRegistrants.notifyRegistrants(); 537 setExternalState(State.PIN_REQUIRED); 538 break; 539 case APPSTATE_PUK: 540 setExternalState(State.PUK_REQUIRED); 541 break; 542 case APPSTATE_DETECTED: 543 case APPSTATE_READY: 544 case APPSTATE_SUBSCRIPTION_PERSO: 545 case APPSTATE_UNKNOWN: 546 // Neither required 547 break; 548 } 549 } 550 } 551 552 private void setExternalState(State newState) { 553 setExternalState(newState, false); 554 } 555 556 public boolean getIccRecordsLoaded() { 557 synchronized (mLock) { 558 if (mIccRecords != null) { 559 return mIccRecords.getRecordsLoaded(); 560 } 561 return false; 562 } 563 } 564 565 private String getIccStateIntentString(State state) { 566 switch (state) { 567 case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT; 568 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 569 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 570 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 571 case READY: return IccCardConstants.INTENT_VALUE_ICC_READY; 572 case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY; 573 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 574 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 575 default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN; 576 } 577 } 578 579 /** 580 * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED, CARD_IO_ERROR) 581 * @return reason 582 */ 583 private String getIccStateReason(State state) { 584 switch (state) { 585 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN; 586 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK; 587 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK; 588 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED; 589 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 590 default: return null; 591 } 592 } 593 594 /* IccCard interface implementation */ 595 @Override 596 public State getState() { 597 synchronized (mLock) { 598 return mExternalState; 599 } 600 } 601 602 @Override 603 public IccRecords getIccRecords() { 604 synchronized (mLock) { 605 return mIccRecords; 606 } 607 } 608 609 @Override 610 public IccFileHandler getIccFileHandler() { 611 synchronized (mLock) { 612 if (mUiccApplication != null) { 613 return mUiccApplication.getIccFileHandler(); 614 } 615 return null; 616 } 617 } 618 619 /** 620 * Notifies handler of any transition into State.ABSENT 621 */ 622 @Override 623 public void registerForAbsent(Handler h, int what, Object obj) { 624 synchronized (mLock) { 625 Registrant r = new Registrant (h, what, obj); 626 627 mAbsentRegistrants.add(r); 628 629 if (getState() == State.ABSENT) { 630 r.notifyRegistrant(); 631 } 632 } 633 } 634 635 @Override 636 public void unregisterForAbsent(Handler h) { 637 synchronized (mLock) { 638 mAbsentRegistrants.remove(h); 639 } 640 } 641 642 /** 643 * Notifies handler of any transition into State.NETWORK_LOCKED 644 */ 645 @Override 646 public void registerForNetworkLocked(Handler h, int what, Object obj) { 647 synchronized (mLock) { 648 Registrant r = new Registrant (h, what, obj); 649 650 mNetworkLockedRegistrants.add(r); 651 652 if (getState() == State.NETWORK_LOCKED) { 653 r.notifyRegistrant(); 654 } 655 } 656 } 657 658 @Override 659 public void unregisterForNetworkLocked(Handler h) { 660 synchronized (mLock) { 661 mNetworkLockedRegistrants.remove(h); 662 } 663 } 664 665 /** 666 * Notifies handler of any transition into State.isPinLocked() 667 */ 668 @Override 669 public void registerForLocked(Handler h, int what, Object obj) { 670 synchronized (mLock) { 671 Registrant r = new Registrant (h, what, obj); 672 673 mPinLockedRegistrants.add(r); 674 675 if (getState().isPinLocked()) { 676 r.notifyRegistrant(); 677 } 678 } 679 } 680 681 @Override 682 public void unregisterForLocked(Handler h) { 683 synchronized (mLock) { 684 mPinLockedRegistrants.remove(h); 685 } 686 } 687 688 @Override 689 public void supplyPin(String pin, Message onComplete) { 690 synchronized (mLock) { 691 if (mUiccApplication != null) { 692 mUiccApplication.supplyPin(pin, onComplete); 693 } else if (onComplete != null) { 694 Exception e = new RuntimeException("ICC card is absent."); 695 AsyncResult.forMessage(onComplete).exception = e; 696 onComplete.sendToTarget(); 697 return; 698 } 699 } 700 } 701 702 @Override 703 public void supplyPuk(String puk, String newPin, Message onComplete) { 704 synchronized (mLock) { 705 if (mUiccApplication != null) { 706 mUiccApplication.supplyPuk(puk, newPin, onComplete); 707 } else if (onComplete != null) { 708 Exception e = new RuntimeException("ICC card is absent."); 709 AsyncResult.forMessage(onComplete).exception = e; 710 onComplete.sendToTarget(); 711 return; 712 } 713 } 714 } 715 716 @Override 717 public void supplyPin2(String pin2, Message onComplete) { 718 synchronized (mLock) { 719 if (mUiccApplication != null) { 720 mUiccApplication.supplyPin2(pin2, onComplete); 721 } else if (onComplete != null) { 722 Exception e = new RuntimeException("ICC card is absent."); 723 AsyncResult.forMessage(onComplete).exception = e; 724 onComplete.sendToTarget(); 725 return; 726 } 727 } 728 } 729 730 @Override 731 public void supplyPuk2(String puk2, String newPin2, Message onComplete) { 732 synchronized (mLock) { 733 if (mUiccApplication != null) { 734 mUiccApplication.supplyPuk2(puk2, newPin2, onComplete); 735 } else if (onComplete != null) { 736 Exception e = new RuntimeException("ICC card is absent."); 737 AsyncResult.forMessage(onComplete).exception = e; 738 onComplete.sendToTarget(); 739 return; 740 } 741 } 742 } 743 744 @Override 745 public void supplyNetworkDepersonalization(String pin, Message onComplete) { 746 synchronized (mLock) { 747 if (mUiccApplication != null) { 748 mUiccApplication.supplyNetworkDepersonalization(pin, onComplete); 749 } else if (onComplete != null) { 750 Exception e = new RuntimeException("CommandsInterface is not set."); 751 AsyncResult.forMessage(onComplete).exception = e; 752 onComplete.sendToTarget(); 753 return; 754 } 755 } 756 } 757 758 @Override 759 public boolean getIccLockEnabled() { 760 synchronized (mLock) { 761 /* defaults to false, if ICC is absent/deactivated */ 762 Boolean retValue = mUiccApplication != null ? 763 mUiccApplication.getIccLockEnabled() : false; 764 return retValue; 765 } 766 } 767 768 @Override 769 public boolean getIccFdnEnabled() { 770 synchronized (mLock) { 771 Boolean retValue = mUiccApplication != null ? 772 mUiccApplication.getIccFdnEnabled() : false; 773 return retValue; 774 } 775 } 776 777 public boolean getIccFdnAvailable() { 778 boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnAvailable() : false; 779 return retValue; 780 } 781 782 public boolean getIccPin2Blocked() { 783 /* defaults to disabled */ 784 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPin2Blocked() : false; 785 return retValue; 786 } 787 788 public boolean getIccPuk2Blocked() { 789 /* defaults to disabled */ 790 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPuk2Blocked() : false; 791 return retValue; 792 } 793 794 @Override 795 public void setIccLockEnabled(boolean enabled, String password, Message onComplete) { 796 synchronized (mLock) { 797 if (mUiccApplication != null) { 798 mUiccApplication.setIccLockEnabled(enabled, password, onComplete); 799 } else if (onComplete != null) { 800 Exception e = new RuntimeException("ICC card is absent."); 801 AsyncResult.forMessage(onComplete).exception = e; 802 onComplete.sendToTarget(); 803 return; 804 } 805 } 806 } 807 808 @Override 809 public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) { 810 synchronized (mLock) { 811 if (mUiccApplication != null) { 812 mUiccApplication.setIccFdnEnabled(enabled, password, onComplete); 813 } else if (onComplete != null) { 814 Exception e = new RuntimeException("ICC card is absent."); 815 AsyncResult.forMessage(onComplete).exception = e; 816 onComplete.sendToTarget(); 817 return; 818 } 819 } 820 } 821 822 @Override 823 public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) { 824 synchronized (mLock) { 825 if (mUiccApplication != null) { 826 mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete); 827 } else if (onComplete != null) { 828 Exception e = new RuntimeException("ICC card is absent."); 829 AsyncResult.forMessage(onComplete).exception = e; 830 onComplete.sendToTarget(); 831 return; 832 } 833 } 834 } 835 836 @Override 837 public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) { 838 synchronized (mLock) { 839 if (mUiccApplication != null) { 840 mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete); 841 } else if (onComplete != null) { 842 Exception e = new RuntimeException("ICC card is absent."); 843 AsyncResult.forMessage(onComplete).exception = e; 844 onComplete.sendToTarget(); 845 return; 846 } 847 } 848 } 849 850 @Override 851 public String getServiceProviderName() { 852 synchronized (mLock) { 853 if (mIccRecords != null) { 854 return mIccRecords.getServiceProviderName(); 855 } 856 return null; 857 } 858 } 859 860 @Override 861 public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) { 862 synchronized (mLock) { 863 Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false; 864 return retValue; 865 } 866 } 867 868 @Override 869 public boolean hasIccCard() { 870 synchronized (mLock) { 871 if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) { 872 return true; 873 } 874 return false; 875 } 876 } 877 878 private void setSystemProperty(String property, int slotId, String value) { 879 // FIXME: Add SubscriptionController.getPhoneIdUsingSlotId 880 long[] subId = SubscriptionController.getInstance().getSubIdUsingSlotId(slotId); 881 if (subId != null && subId.length > 0) { 882 int phoneId = SubscriptionController.getInstance().getPhoneId(subId[0]); 883 TelephonyManager.setTelephonyProperty(phoneId, property, value); 884 } else { 885 loge("setSystemProperty: subId is null or subId.length == 0"); 886 } 887 } 888 889 private void log(String s) { 890 Rlog.d(LOG_TAG, s); 891 } 892 893 private void loge(String msg) { 894 Rlog.e(LOG_TAG, msg); 895 } 896 897 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 898 pw.println("IccCardProxy: " + this); 899 pw.println(" mContext=" + mContext); 900 pw.println(" mCi=" + mCi); 901 pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size()); 902 for (int i = 0; i < mAbsentRegistrants.size(); i++) { 903 pw.println(" mAbsentRegistrants[" + i + "]=" 904 + ((Registrant)mAbsentRegistrants.get(i)).getHandler()); 905 } 906 pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size()); 907 for (int i = 0; i < mPinLockedRegistrants.size(); i++) { 908 pw.println(" mPinLockedRegistrants[" + i + "]=" 909 + ((Registrant)mPinLockedRegistrants.get(i)).getHandler()); 910 } 911 pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size()); 912 for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) { 913 pw.println(" mNetworkLockedRegistrants[" + i + "]=" 914 + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler()); 915 } 916 pw.println(" mCurrentAppType=" + mCurrentAppType); 917 pw.println(" mUiccController=" + mUiccController); 918 pw.println(" mUiccCard=" + mUiccCard); 919 pw.println(" mUiccApplication=" + mUiccApplication); 920 pw.println(" mIccRecords=" + mIccRecords); 921 pw.println(" mCdmaSSM=" + mCdmaSSM); 922 pw.println(" mRadioOn=" + mRadioOn); 923 pw.println(" mQuietMode=" + mQuietMode); 924 pw.println(" mInitialized=" + mInitialized); 925 pw.println(" mExternalState=" + mExternalState); 926 927 pw.flush(); 928 } 929} 930