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