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