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