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 17 package com.android.internal.telephony.uicc; 18 19 import static android.Manifest.permission.READ_PHONE_STATE; 20 21 import android.app.ActivityManagerNative; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.os.AsyncResult; 25 import android.os.Handler; 26 import android.os.Message; 27 import android.os.Registrant; 28 import android.os.RegistrantList; 29 import android.os.SystemProperties; 30 import android.os.UserHandle; 31 import android.telephony.Rlog; 32 import android.telephony.ServiceState; 33 import android.telephony.SubscriptionManager; 34 import android.telephony.TelephonyManager; 35 36 import com.android.internal.telephony.CommandsInterface; 37 import com.android.internal.telephony.IccCard; 38 import com.android.internal.telephony.IccCardConstants; 39 import com.android.internal.telephony.PhoneConstants; 40 import com.android.internal.telephony.MccTable; 41 import com.android.internal.telephony.RILConstants; 42 import com.android.internal.telephony.TelephonyIntents; 43 import com.android.internal.telephony.IccCardConstants.State; 44 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 45 import com.android.internal.telephony.Phone; 46 import com.android.internal.telephony.Subscription; 47 import com.android.internal.telephony.SubscriptionController; 48 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 49 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState; 50 import com.android.internal.telephony.uicc.IccCardStatus.CardState; 51 import com.android.internal.telephony.uicc.IccCardStatus.PinState; 52 import com.android.internal.telephony.uicc.UiccController; 53 54 import java.io.FileDescriptor; 55 import java.io.PrintWriter; 56 57 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; 58 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; 59 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; 60 import 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 81 public 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 if (CommandsInterface.RadioState.RADIO_UNAVAILABLE == mCi.getRadioState()) { 234 setExternalState(State.NOT_READY); 235 } 236 break; 237 case EVENT_RADIO_ON: 238 mRadioOn = true; 239 if (!mInitialized) { 240 updateQuietMode(); 241 } 242 break; 243 case EVENT_ICC_CHANGED: 244 if (mInitialized) { 245 updateIccAvailability(); 246 } 247 break; 248 case EVENT_ICC_ABSENT: 249 mAbsentRegistrants.notifyRegistrants(); 250 setExternalState(State.ABSENT); 251 break; 252 case EVENT_ICC_LOCKED: 253 processLockedState(); 254 break; 255 case EVENT_APP_READY: 256 setExternalState(State.READY); 257 break; 258 case EVENT_RECORDS_LOADED: 259 if (mIccRecords != null) { 260 String operator = mIccRecords.getOperatorNumeric(); 261 int slotId = mCardIndex; 262 263 log("operator = " + operator + " slotId = " + slotId); 264 265 if (operator != null) { 266 log("update icc_operator_numeric=" + operator); 267 setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, slotId, operator); 268 String countryCode = operator.substring(0,3); 269 if (countryCode != null) { 270 setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, slotId, 271 MccTable.countryCodeForMcc(Integer.parseInt(countryCode))); 272 } else { 273 loge("EVENT_RECORDS_LOADED Country code is null"); 274 } 275 276 long[] subId = SubscriptionController.getInstance().getSubId(slotId); 277 // Update MCC MNC device configuration information only for default sub. 278 if (subId[0] == SubscriptionController.getInstance().getDefaultSubId()) { 279 log("update mccmnc=" + operator + " config for default subscription."); 280 MccTable.updateMccMncConfiguration(mContext, operator, false); 281 } 282 SubscriptionController.getInstance().setMccMnc(operator, subId[0]); 283 } else { 284 loge("EVENT_RECORDS_LOADED Operator name is null"); 285 } 286 } 287 if (mUiccCard != null && !mUiccCard.areCarrierPriviligeRulesLoaded()) { 288 mUiccCard.registerForCarrierPrivilegeRulesLoaded( 289 this, EVENT_CARRIER_PRIVILIGES_LOADED, null); 290 } else { 291 onRecordsLoaded(); 292 } 293 break; 294 case EVENT_IMSI_READY: 295 broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_IMSI, null); 296 break; 297 case EVENT_NETWORK_LOCKED: 298 mNetworkLockedRegistrants.notifyRegistrants(); 299 setExternalState(State.NETWORK_LOCKED); 300 break; 301 case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED: 302 updateQuietMode(); 303 break; 304 case EVENT_SUBSCRIPTION_ACTIVATED: 305 log("EVENT_SUBSCRIPTION_ACTIVATED"); 306 onSubscriptionActivated(); 307 break; 308 309 case EVENT_SUBSCRIPTION_DEACTIVATED: 310 log("EVENT_SUBSCRIPTION_DEACTIVATED"); 311 onSubscriptionDeactivated(); 312 break; 313 314 case EVENT_ICC_RECORD_EVENTS: 315 if ((mCurrentAppType == UiccController.APP_FAM_3GPP) && (mIccRecords != null)) { 316 int slotId = mCardIndex; 317 AsyncResult ar = (AsyncResult)msg.obj; 318 int eventCode = (Integer) ar.result; 319 if (eventCode == SIMRecords.EVENT_SPN) { 320 setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, slotId, 321 mIccRecords.getServiceProviderName()); 322 } 323 } 324 break; 325 326 case EVENT_CARRIER_PRIVILIGES_LOADED: 327 log("EVENT_CARRIER_PRIVILEGES_LOADED"); 328 if (mUiccCard != null) { 329 mUiccCard.unregisterForCarrierPrivilegeRulesLoaded(this); 330 } 331 onRecordsLoaded(); 332 break; 333 334 default: 335 loge("Unhandled message with number: " + msg.what); 336 break; 337 } 338 } 339 340 private void onSubscriptionActivated() { 341 //mSubscriptionData = SubscriptionManager.getCurrentSubscription(mCardIndex); 342 343 updateIccAvailability(); 344 updateStateProperty(); 345 } 346 347 private void onSubscriptionDeactivated() { 348 resetProperties(); 349 mSubscriptionData = null; 350 updateIccAvailability(); 351 updateStateProperty(); 352 } 353 354 private void onRecordsLoaded() { 355 broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null); 356 } 357 358 private void updateIccAvailability() { 359 synchronized (mLock) { 360 UiccCard newCard = mUiccController.getUiccCard(mCardIndex); 361 CardState state = CardState.CARDSTATE_ABSENT; 362 UiccCardApplication newApp = null; 363 IccRecords newRecords = null; 364 if (newCard != null) { 365 state = newCard.getCardState(); 366 newApp = newCard.getApplication(mCurrentAppType); 367 if (newApp != null) { 368 newRecords = newApp.getIccRecords(); 369 } 370 } 371 372 if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) { 373 if (DBG) log("Icc changed. Reregestering."); 374 unregisterUiccCardEvents(); 375 mUiccCard = newCard; 376 mUiccApplication = newApp; 377 mIccRecords = newRecords; 378 registerUiccCardEvents(); 379 } 380 381 updateExternalState(); 382 } 383 } 384 385 void resetProperties() { 386 if (mCurrentAppType == UiccController.APP_FAM_3GPP) { 387 log("update icc_operator_numeric=" + ""); 388 setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, mCardIndex, ""); 389 setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, mCardIndex, ""); 390 setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, mCardIndex, ""); 391 } 392 } 393 394 private void HandleDetectedState() { 395 // CAF_MSIM SAND 396 // setExternalState(State.DETECTED, false); 397 } 398 399 private void updateExternalState() { 400 if (mUiccCard == null || mUiccCard.getCardState() == CardState.CARDSTATE_ABSENT) { 401 if (mRadioOn) { 402 setExternalState(State.ABSENT); 403 } else { 404 setExternalState(State.NOT_READY); 405 } 406 return; 407 } 408 409 if (mUiccCard.getCardState() == CardState.CARDSTATE_ERROR) { 410 setExternalState(State.CARD_IO_ERROR); 411 return; 412 } 413 414 if (mUiccApplication == null) { 415 setExternalState(State.NOT_READY); 416 return; 417 } 418 419 switch (mUiccApplication.getState()) { 420 case APPSTATE_UNKNOWN: 421 setExternalState(State.UNKNOWN); 422 break; 423 case APPSTATE_DETECTED: 424 HandleDetectedState(); 425 break; 426 case APPSTATE_PIN: 427 setExternalState(State.PIN_REQUIRED); 428 break; 429 case APPSTATE_PUK: 430 setExternalState(State.PUK_REQUIRED); 431 break; 432 case APPSTATE_SUBSCRIPTION_PERSO: 433 if (mUiccApplication.getPersoSubState() == 434 PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 435 setExternalState(State.NETWORK_LOCKED); 436 } else { 437 setExternalState(State.UNKNOWN); 438 } 439 break; 440 case APPSTATE_READY: 441 setExternalState(State.READY); 442 break; 443 } 444 } 445 446 private void registerUiccCardEvents() { 447 if (mUiccCard != null) { 448 mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null); 449 } 450 if (mUiccApplication != null) { 451 mUiccApplication.registerForReady(this, EVENT_APP_READY, null); 452 mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null); 453 mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null); 454 } 455 if (mIccRecords != null) { 456 mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null); 457 mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null); 458 mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); 459 } 460 } 461 462 private void unregisterUiccCardEvents() { 463 if (mUiccCard != null) mUiccCard.unregisterForAbsent(this); 464 if (mUiccApplication != null) mUiccApplication.unregisterForReady(this); 465 if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this); 466 if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this); 467 if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this); 468 if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this); 469 if (mIccRecords != null) mIccRecords.unregisterForRecordsEvents(this); 470 } 471 472 private void updateStateProperty() { 473 setSystemProperty(PROPERTY_SIM_STATE, mCardIndex,getState().toString()); 474 } 475 476 private void broadcastIccStateChangedIntent(String value, String reason) { 477 synchronized (mLock) { 478 if (mCardIndex == null) { 479 loge("broadcastIccStateChangedIntent: Card Index is not set; Return!!"); 480 return; 481 } 482 483 if (mQuietMode) { 484 log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " + value 485 + " reason " + reason); 486 return; 487 } 488 489 Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 490 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 491 intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 492 intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value); 493 intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 494 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mCardIndex); 495 log("Broadcasting intent ACTION_SIM_STATE_CHANGED " + value 496 + " reason " + reason + " for mCardIndex : " + mCardIndex); 497 ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE, 498 UserHandle.USER_ALL); 499 } 500 } 501 502 private void setExternalState(State newState, boolean override) { 503 synchronized (mLock) { 504 if (mCardIndex == null) { 505 loge("setExternalState: Card Index is not set; Return!!"); 506 return; 507 } 508 509 if (!override && newState == mExternalState) { 510 return; 511 } 512 mExternalState = newState; 513 setSystemProperty(PROPERTY_SIM_STATE, mCardIndex, getState().toString()); 514 broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState), 515 getIccStateReason(mExternalState)); 516 // TODO: Need to notify registrants for other states as well. 517 if ( State.ABSENT == mExternalState) { 518 mAbsentRegistrants.notifyRegistrants(); 519 } 520 } 521 } 522 523 private void processLockedState() { 524 synchronized (mLock) { 525 if (mUiccApplication == null) { 526 //Don't need to do anything if non-existent application is locked 527 return; 528 } 529 PinState pin1State = mUiccApplication.getPin1State(); 530 if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) { 531 setExternalState(State.PERM_DISABLED); 532 return; 533 } 534 535 AppState appState = mUiccApplication.getState(); 536 switch (appState) { 537 case APPSTATE_PIN: 538 mPinLockedRegistrants.notifyRegistrants(); 539 setExternalState(State.PIN_REQUIRED); 540 break; 541 case APPSTATE_PUK: 542 setExternalState(State.PUK_REQUIRED); 543 break; 544 case APPSTATE_DETECTED: 545 case APPSTATE_READY: 546 case APPSTATE_SUBSCRIPTION_PERSO: 547 case APPSTATE_UNKNOWN: 548 // Neither required 549 break; 550 } 551 } 552 } 553 554 private void setExternalState(State newState) { 555 setExternalState(newState, false); 556 } 557 558 public boolean getIccRecordsLoaded() { 559 synchronized (mLock) { 560 if (mIccRecords != null) { 561 return mIccRecords.getRecordsLoaded(); 562 } 563 return false; 564 } 565 } 566 567 private String getIccStateIntentString(State state) { 568 switch (state) { 569 case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT; 570 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 571 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 572 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 573 case READY: return IccCardConstants.INTENT_VALUE_ICC_READY; 574 case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY; 575 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 576 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 577 default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN; 578 } 579 } 580 581 /** 582 * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED, CARD_IO_ERROR) 583 * @return reason 584 */ 585 private String getIccStateReason(State state) { 586 switch (state) { 587 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN; 588 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK; 589 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK; 590 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED; 591 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 592 default: return null; 593 } 594 } 595 596 /* IccCard interface implementation */ 597 @Override 598 public State getState() { 599 synchronized (mLock) { 600 return mExternalState; 601 } 602 } 603 604 @Override 605 public IccRecords getIccRecords() { 606 synchronized (mLock) { 607 return mIccRecords; 608 } 609 } 610 611 @Override 612 public IccFileHandler getIccFileHandler() { 613 synchronized (mLock) { 614 if (mUiccApplication != null) { 615 return mUiccApplication.getIccFileHandler(); 616 } 617 return null; 618 } 619 } 620 621 /** 622 * Notifies handler of any transition into State.ABSENT 623 */ 624 @Override 625 public void registerForAbsent(Handler h, int what, Object obj) { 626 synchronized (mLock) { 627 Registrant r = new Registrant (h, what, obj); 628 629 mAbsentRegistrants.add(r); 630 631 if (getState() == State.ABSENT) { 632 r.notifyRegistrant(); 633 } 634 } 635 } 636 637 @Override 638 public void unregisterForAbsent(Handler h) { 639 synchronized (mLock) { 640 mAbsentRegistrants.remove(h); 641 } 642 } 643 644 /** 645 * Notifies handler of any transition into State.NETWORK_LOCKED 646 */ 647 @Override 648 public void registerForNetworkLocked(Handler h, int what, Object obj) { 649 synchronized (mLock) { 650 Registrant r = new Registrant (h, what, obj); 651 652 mNetworkLockedRegistrants.add(r); 653 654 if (getState() == State.NETWORK_LOCKED) { 655 r.notifyRegistrant(); 656 } 657 } 658 } 659 660 @Override 661 public void unregisterForNetworkLocked(Handler h) { 662 synchronized (mLock) { 663 mNetworkLockedRegistrants.remove(h); 664 } 665 } 666 667 /** 668 * Notifies handler of any transition into State.isPinLocked() 669 */ 670 @Override 671 public void registerForLocked(Handler h, int what, Object obj) { 672 synchronized (mLock) { 673 Registrant r = new Registrant (h, what, obj); 674 675 mPinLockedRegistrants.add(r); 676 677 if (getState().isPinLocked()) { 678 r.notifyRegistrant(); 679 } 680 } 681 } 682 683 @Override 684 public void unregisterForLocked(Handler h) { 685 synchronized (mLock) { 686 mPinLockedRegistrants.remove(h); 687 } 688 } 689 690 @Override 691 public void supplyPin(String pin, Message onComplete) { 692 synchronized (mLock) { 693 if (mUiccApplication != null) { 694 mUiccApplication.supplyPin(pin, onComplete); 695 } else if (onComplete != null) { 696 Exception e = new RuntimeException("ICC card is absent."); 697 AsyncResult.forMessage(onComplete).exception = e; 698 onComplete.sendToTarget(); 699 return; 700 } 701 } 702 } 703 704 @Override 705 public void supplyPuk(String puk, String newPin, Message onComplete) { 706 synchronized (mLock) { 707 if (mUiccApplication != null) { 708 mUiccApplication.supplyPuk(puk, newPin, onComplete); 709 } else if (onComplete != null) { 710 Exception e = new RuntimeException("ICC card is absent."); 711 AsyncResult.forMessage(onComplete).exception = e; 712 onComplete.sendToTarget(); 713 return; 714 } 715 } 716 } 717 718 @Override 719 public void supplyPin2(String pin2, Message onComplete) { 720 synchronized (mLock) { 721 if (mUiccApplication != null) { 722 mUiccApplication.supplyPin2(pin2, onComplete); 723 } else if (onComplete != null) { 724 Exception e = new RuntimeException("ICC card is absent."); 725 AsyncResult.forMessage(onComplete).exception = e; 726 onComplete.sendToTarget(); 727 return; 728 } 729 } 730 } 731 732 @Override 733 public void supplyPuk2(String puk2, String newPin2, Message onComplete) { 734 synchronized (mLock) { 735 if (mUiccApplication != null) { 736 mUiccApplication.supplyPuk2(puk2, newPin2, onComplete); 737 } else if (onComplete != null) { 738 Exception e = new RuntimeException("ICC card is absent."); 739 AsyncResult.forMessage(onComplete).exception = e; 740 onComplete.sendToTarget(); 741 return; 742 } 743 } 744 } 745 746 @Override 747 public void supplyNetworkDepersonalization(String pin, Message onComplete) { 748 synchronized (mLock) { 749 if (mUiccApplication != null) { 750 mUiccApplication.supplyNetworkDepersonalization(pin, onComplete); 751 } else if (onComplete != null) { 752 Exception e = new RuntimeException("CommandsInterface is not set."); 753 AsyncResult.forMessage(onComplete).exception = e; 754 onComplete.sendToTarget(); 755 return; 756 } 757 } 758 } 759 760 @Override 761 public boolean getIccLockEnabled() { 762 synchronized (mLock) { 763 /* defaults to false, if ICC is absent/deactivated */ 764 Boolean retValue = mUiccApplication != null ? 765 mUiccApplication.getIccLockEnabled() : false; 766 return retValue; 767 } 768 } 769 770 @Override 771 public boolean getIccFdnEnabled() { 772 synchronized (mLock) { 773 Boolean retValue = mUiccApplication != null ? 774 mUiccApplication.getIccFdnEnabled() : false; 775 return retValue; 776 } 777 } 778 779 public boolean getIccFdnAvailable() { 780 boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnAvailable() : false; 781 return retValue; 782 } 783 784 public boolean getIccPin2Blocked() { 785 /* defaults to disabled */ 786 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPin2Blocked() : false; 787 return retValue; 788 } 789 790 public boolean getIccPuk2Blocked() { 791 /* defaults to disabled */ 792 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPuk2Blocked() : false; 793 return retValue; 794 } 795 796 @Override 797 public void setIccLockEnabled(boolean enabled, String password, Message onComplete) { 798 synchronized (mLock) { 799 if (mUiccApplication != null) { 800 mUiccApplication.setIccLockEnabled(enabled, password, onComplete); 801 } else if (onComplete != null) { 802 Exception e = new RuntimeException("ICC card is absent."); 803 AsyncResult.forMessage(onComplete).exception = e; 804 onComplete.sendToTarget(); 805 return; 806 } 807 } 808 } 809 810 @Override 811 public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) { 812 synchronized (mLock) { 813 if (mUiccApplication != null) { 814 mUiccApplication.setIccFdnEnabled(enabled, password, onComplete); 815 } else if (onComplete != null) { 816 Exception e = new RuntimeException("ICC card is absent."); 817 AsyncResult.forMessage(onComplete).exception = e; 818 onComplete.sendToTarget(); 819 return; 820 } 821 } 822 } 823 824 @Override 825 public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) { 826 synchronized (mLock) { 827 if (mUiccApplication != null) { 828 mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete); 829 } else if (onComplete != null) { 830 Exception e = new RuntimeException("ICC card is absent."); 831 AsyncResult.forMessage(onComplete).exception = e; 832 onComplete.sendToTarget(); 833 return; 834 } 835 } 836 } 837 838 @Override 839 public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) { 840 synchronized (mLock) { 841 if (mUiccApplication != null) { 842 mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete); 843 } else if (onComplete != null) { 844 Exception e = new RuntimeException("ICC card is absent."); 845 AsyncResult.forMessage(onComplete).exception = e; 846 onComplete.sendToTarget(); 847 return; 848 } 849 } 850 } 851 852 @Override 853 public String getServiceProviderName() { 854 synchronized (mLock) { 855 if (mIccRecords != null) { 856 return mIccRecords.getServiceProviderName(); 857 } 858 return null; 859 } 860 } 861 862 @Override 863 public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) { 864 synchronized (mLock) { 865 Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false; 866 return retValue; 867 } 868 } 869 870 @Override 871 public boolean hasIccCard() { 872 synchronized (mLock) { 873 if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) { 874 return true; 875 } 876 return false; 877 } 878 } 879 880 private void setSystemProperty(String property, int slotId, String value) { 881 long[] subId = SubscriptionController.getInstance().getSubId(slotId); 882 TelephonyManager.setTelephonyProperty(property, subId[0], value); 883 } 884 885 private void log(String s) { 886 Rlog.d(LOG_TAG, s); 887 } 888 889 private void loge(String msg) { 890 Rlog.e(LOG_TAG, msg); 891 } 892 893 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 894 pw.println("IccCardProxy: " + this); 895 pw.println(" mContext=" + mContext); 896 pw.println(" mCi=" + mCi); 897 pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size()); 898 for (int i = 0; i < mAbsentRegistrants.size(); i++) { 899 pw.println(" mAbsentRegistrants[" + i + "]=" 900 + ((Registrant)mAbsentRegistrants.get(i)).getHandler()); 901 } 902 pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size()); 903 for (int i = 0; i < mPinLockedRegistrants.size(); i++) { 904 pw.println(" mPinLockedRegistrants[" + i + "]=" 905 + ((Registrant)mPinLockedRegistrants.get(i)).getHandler()); 906 } 907 pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size()); 908 for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) { 909 pw.println(" mNetworkLockedRegistrants[" + i + "]=" 910 + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler()); 911 } 912 pw.println(" mCurrentAppType=" + mCurrentAppType); 913 pw.println(" mUiccController=" + mUiccController); 914 pw.println(" mUiccCard=" + mUiccCard); 915 pw.println(" mUiccApplication=" + mUiccApplication); 916 pw.println(" mIccRecords=" + mIccRecords); 917 pw.println(" mCdmaSSM=" + mCdmaSSM); 918 pw.println(" mRadioOn=" + mRadioOn); 919 pw.println(" mQuietMode=" + mQuietMode); 920 pw.println(" mInitialized=" + mInitialized); 921 pw.println(" mExternalState=" + mExternalState); 922 923 pw.flush(); 924 } 925 } 926