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 updateExternalState(); 366 } 367 } 368 resetProperties()369 void resetProperties() { 370 if (mCurrentAppType == UiccController.APP_FAM_3GPP) { 371 log("update icc_operator_numeric=" + ""); 372 mTelephonyManager.setSimOperatorNumericForPhone(mPhoneId, ""); 373 mTelephonyManager.setSimCountryIsoForPhone(mPhoneId, ""); 374 mTelephonyManager.setSimOperatorNameForPhone(mPhoneId, ""); 375 } 376 } 377 HandleDetectedState()378 private void HandleDetectedState() { 379 // CAF_MSIM SAND 380 // setExternalState(State.DETECTED, false); 381 } 382 updateExternalState()383 private void updateExternalState() { 384 385 // mUiccCard could be null at bootup, before valid card states have 386 // been received from UiccController. 387 if (mUiccCard == null) { 388 setExternalState(State.NOT_READY); 389 return; 390 } 391 392 if (mUiccCard.getCardState() == CardState.CARDSTATE_ABSENT) { 393 if (mRadioOn) { 394 setExternalState(State.ABSENT); 395 } else { 396 setExternalState(State.NOT_READY); 397 } 398 return; 399 } 400 401 if (mUiccCard.getCardState() == CardState.CARDSTATE_ERROR) { 402 setExternalState(State.CARD_IO_ERROR); 403 return; 404 } 405 406 if (mUiccApplication == null) { 407 setExternalState(State.NOT_READY); 408 return; 409 } 410 411 switch (mUiccApplication.getState()) { 412 case APPSTATE_UNKNOWN: 413 setExternalState(State.UNKNOWN); 414 break; 415 case APPSTATE_DETECTED: 416 HandleDetectedState(); 417 break; 418 case APPSTATE_PIN: 419 setExternalState(State.PIN_REQUIRED); 420 break; 421 case APPSTATE_PUK: 422 setExternalState(State.PUK_REQUIRED); 423 break; 424 case APPSTATE_SUBSCRIPTION_PERSO: 425 if (mUiccApplication.getPersoSubState() == 426 PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 427 setExternalState(State.NETWORK_LOCKED); 428 } else { 429 setExternalState(State.UNKNOWN); 430 } 431 break; 432 case APPSTATE_READY: 433 setExternalState(State.READY); 434 break; 435 } 436 } 437 registerUiccCardEvents()438 private void registerUiccCardEvents() { 439 if (mUiccCard != null) { 440 mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null); 441 } 442 if (mUiccApplication != null) { 443 mUiccApplication.registerForReady(this, EVENT_APP_READY, null); 444 mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null); 445 mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null); 446 } 447 if (mIccRecords != null) { 448 mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null); 449 mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null); 450 mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); 451 } 452 } 453 unregisterUiccCardEvents()454 private void unregisterUiccCardEvents() { 455 if (mUiccCard != null) mUiccCard.unregisterForAbsent(this); 456 if (mUiccApplication != null) mUiccApplication.unregisterForReady(this); 457 if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this); 458 if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this); 459 if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this); 460 if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this); 461 if (mIccRecords != null) mIccRecords.unregisterForRecordsEvents(this); 462 } 463 updateStateProperty()464 private void updateStateProperty() { 465 mTelephonyManager.setSimStateForPhone(mPhoneId, getState().toString()); 466 } 467 broadcastIccStateChangedIntent(String value, String reason)468 private void broadcastIccStateChangedIntent(String value, String reason) { 469 synchronized (mLock) { 470 if (mPhoneId == null || !SubscriptionManager.isValidSlotId(mPhoneId)) { 471 loge("broadcastIccStateChangedIntent: mPhoneId=" + mPhoneId 472 + " is invalid; Return!!"); 473 return; 474 } 475 476 if (mQuietMode) { 477 log("broadcastIccStateChangedIntent: QuietMode" 478 + " NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " 479 + " value=" + value + " reason=" + reason); 480 return; 481 } 482 483 Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 484 // TODO - we'd like this intent to have a single snapshot of all sim state, 485 // but until then this should not use REPLACE_PENDING or we may lose 486 // information 487 // intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 488 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 489 intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 490 intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value); 491 intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 492 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhoneId); 493 log("broadcastIccStateChangedIntent intent ACTION_SIM_STATE_CHANGED value=" + value 494 + " reason=" + reason + " for mPhoneId=" + mPhoneId); 495 ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE, 496 UserHandle.USER_ALL); 497 } 498 } 499 broadcastInternalIccStateChangedIntent(String value, String reason)500 private void broadcastInternalIccStateChangedIntent(String value, String reason) { 501 synchronized (mLock) { 502 if (mPhoneId == null) { 503 loge("broadcastInternalIccStateChangedIntent: Card Index is not set; Return!!"); 504 return; 505 } 506 507 Intent intent = new Intent(ACTION_INTERNAL_SIM_STATE_CHANGED); 508 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 509 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 510 intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 511 intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value); 512 intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 513 intent.putExtra(PhoneConstants.PHONE_KEY, mPhoneId); // SubId may not be valid. 514 log("Sending intent ACTION_INTERNAL_SIM_STATE_CHANGED" + " for mPhoneId : " + mPhoneId); 515 ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 516 } 517 } 518 setExternalState(State newState, boolean override)519 private void setExternalState(State newState, boolean override) { 520 synchronized (mLock) { 521 if (mPhoneId == null || !SubscriptionManager.isValidSlotId(mPhoneId)) { 522 loge("setExternalState: mPhoneId=" + mPhoneId + " is invalid; Return!!"); 523 return; 524 } 525 526 if (!override && newState == mExternalState) { 527 loge("setExternalState: !override and newstate unchanged from " + newState); 528 return; 529 } 530 mExternalState = newState; 531 loge("setExternalState: set mPhoneId=" + mPhoneId + " mExternalState=" + mExternalState); 532 mTelephonyManager.setSimStateForPhone(mPhoneId, getState().toString()); 533 534 // For locked states, we should be sending internal broadcast. 535 if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(getIccStateIntentString(mExternalState))) { 536 broadcastInternalIccStateChangedIntent(getIccStateIntentString(mExternalState), 537 getIccStateReason(mExternalState)); 538 } else { 539 broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState), 540 getIccStateReason(mExternalState)); 541 } 542 // TODO: Need to notify registrants for other states as well. 543 if ( State.ABSENT == mExternalState) { 544 mAbsentRegistrants.notifyRegistrants(); 545 } 546 } 547 } 548 processLockedState()549 private void processLockedState() { 550 synchronized (mLock) { 551 if (mUiccApplication == null) { 552 //Don't need to do anything if non-existent application is locked 553 return; 554 } 555 PinState pin1State = mUiccApplication.getPin1State(); 556 if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) { 557 setExternalState(State.PERM_DISABLED); 558 return; 559 } 560 561 AppState appState = mUiccApplication.getState(); 562 switch (appState) { 563 case APPSTATE_PIN: 564 mPinLockedRegistrants.notifyRegistrants(); 565 setExternalState(State.PIN_REQUIRED); 566 break; 567 case APPSTATE_PUK: 568 setExternalState(State.PUK_REQUIRED); 569 break; 570 case APPSTATE_DETECTED: 571 case APPSTATE_READY: 572 case APPSTATE_SUBSCRIPTION_PERSO: 573 case APPSTATE_UNKNOWN: 574 // Neither required 575 break; 576 } 577 } 578 } 579 setExternalState(State newState)580 private void setExternalState(State newState) { 581 setExternalState(newState, false); 582 } 583 getIccRecordsLoaded()584 public boolean getIccRecordsLoaded() { 585 synchronized (mLock) { 586 if (mIccRecords != null) { 587 return mIccRecords.getRecordsLoaded(); 588 } 589 return false; 590 } 591 } 592 getIccStateIntentString(State state)593 private String getIccStateIntentString(State state) { 594 switch (state) { 595 case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT; 596 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 597 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 598 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 599 case READY: return IccCardConstants.INTENT_VALUE_ICC_READY; 600 case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY; 601 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 602 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 603 default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN; 604 } 605 } 606 607 /** 608 * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED, CARD_IO_ERROR) 609 * @return reason 610 */ getIccStateReason(State state)611 private String getIccStateReason(State state) { 612 switch (state) { 613 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN; 614 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK; 615 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK; 616 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED; 617 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 618 default: return null; 619 } 620 } 621 622 /* IccCard interface implementation */ 623 @Override getState()624 public State getState() { 625 synchronized (mLock) { 626 return mExternalState; 627 } 628 } 629 630 @Override getIccRecords()631 public IccRecords getIccRecords() { 632 synchronized (mLock) { 633 return mIccRecords; 634 } 635 } 636 637 @Override getIccFileHandler()638 public IccFileHandler getIccFileHandler() { 639 synchronized (mLock) { 640 if (mUiccApplication != null) { 641 return mUiccApplication.getIccFileHandler(); 642 } 643 return null; 644 } 645 } 646 647 /** 648 * Notifies handler of any transition into State.ABSENT 649 */ 650 @Override registerForAbsent(Handler h, int what, Object obj)651 public void registerForAbsent(Handler h, int what, Object obj) { 652 synchronized (mLock) { 653 Registrant r = new Registrant (h, what, obj); 654 655 mAbsentRegistrants.add(r); 656 657 if (getState() == State.ABSENT) { 658 r.notifyRegistrant(); 659 } 660 } 661 } 662 663 @Override unregisterForAbsent(Handler h)664 public void unregisterForAbsent(Handler h) { 665 synchronized (mLock) { 666 mAbsentRegistrants.remove(h); 667 } 668 } 669 670 /** 671 * Notifies handler of any transition into State.NETWORK_LOCKED 672 */ 673 @Override registerForNetworkLocked(Handler h, int what, Object obj)674 public void registerForNetworkLocked(Handler h, int what, Object obj) { 675 synchronized (mLock) { 676 Registrant r = new Registrant (h, what, obj); 677 678 mNetworkLockedRegistrants.add(r); 679 680 if (getState() == State.NETWORK_LOCKED) { 681 r.notifyRegistrant(); 682 } 683 } 684 } 685 686 @Override unregisterForNetworkLocked(Handler h)687 public void unregisterForNetworkLocked(Handler h) { 688 synchronized (mLock) { 689 mNetworkLockedRegistrants.remove(h); 690 } 691 } 692 693 /** 694 * Notifies handler of any transition into State.isPinLocked() 695 */ 696 @Override registerForLocked(Handler h, int what, Object obj)697 public void registerForLocked(Handler h, int what, Object obj) { 698 synchronized (mLock) { 699 Registrant r = new Registrant (h, what, obj); 700 701 mPinLockedRegistrants.add(r); 702 703 if (getState().isPinLocked()) { 704 r.notifyRegistrant(); 705 } 706 } 707 } 708 709 @Override unregisterForLocked(Handler h)710 public void unregisterForLocked(Handler h) { 711 synchronized (mLock) { 712 mPinLockedRegistrants.remove(h); 713 } 714 } 715 716 @Override supplyPin(String pin, Message onComplete)717 public void supplyPin(String pin, Message onComplete) { 718 synchronized (mLock) { 719 if (mUiccApplication != null) { 720 mUiccApplication.supplyPin(pin, onComplete); 721 } else if (onComplete != null) { 722 Exception e = new RuntimeException("ICC card is absent."); 723 AsyncResult.forMessage(onComplete).exception = e; 724 onComplete.sendToTarget(); 725 return; 726 } 727 } 728 } 729 730 @Override supplyPuk(String puk, String newPin, Message onComplete)731 public void supplyPuk(String puk, String newPin, Message onComplete) { 732 synchronized (mLock) { 733 if (mUiccApplication != null) { 734 mUiccApplication.supplyPuk(puk, newPin, onComplete); 735 } else if (onComplete != null) { 736 Exception e = new RuntimeException("ICC card is absent."); 737 AsyncResult.forMessage(onComplete).exception = e; 738 onComplete.sendToTarget(); 739 return; 740 } 741 } 742 } 743 744 @Override supplyPin2(String pin2, Message onComplete)745 public void supplyPin2(String pin2, Message onComplete) { 746 synchronized (mLock) { 747 if (mUiccApplication != null) { 748 mUiccApplication.supplyPin2(pin2, onComplete); 749 } else if (onComplete != null) { 750 Exception e = new RuntimeException("ICC card is absent."); 751 AsyncResult.forMessage(onComplete).exception = e; 752 onComplete.sendToTarget(); 753 return; 754 } 755 } 756 } 757 758 @Override supplyPuk2(String puk2, String newPin2, Message onComplete)759 public void supplyPuk2(String puk2, String newPin2, Message onComplete) { 760 synchronized (mLock) { 761 if (mUiccApplication != null) { 762 mUiccApplication.supplyPuk2(puk2, newPin2, onComplete); 763 } else if (onComplete != null) { 764 Exception e = new RuntimeException("ICC card is absent."); 765 AsyncResult.forMessage(onComplete).exception = e; 766 onComplete.sendToTarget(); 767 return; 768 } 769 } 770 } 771 772 @Override supplyNetworkDepersonalization(String pin, Message onComplete)773 public void supplyNetworkDepersonalization(String pin, Message onComplete) { 774 synchronized (mLock) { 775 if (mUiccApplication != null) { 776 mUiccApplication.supplyNetworkDepersonalization(pin, onComplete); 777 } else if (onComplete != null) { 778 Exception e = new RuntimeException("CommandsInterface is not set."); 779 AsyncResult.forMessage(onComplete).exception = e; 780 onComplete.sendToTarget(); 781 return; 782 } 783 } 784 } 785 786 @Override getIccLockEnabled()787 public boolean getIccLockEnabled() { 788 synchronized (mLock) { 789 /* defaults to false, if ICC is absent/deactivated */ 790 Boolean retValue = mUiccApplication != null ? 791 mUiccApplication.getIccLockEnabled() : false; 792 return retValue; 793 } 794 } 795 796 @Override getIccFdnEnabled()797 public boolean getIccFdnEnabled() { 798 synchronized (mLock) { 799 Boolean retValue = mUiccApplication != null ? 800 mUiccApplication.getIccFdnEnabled() : false; 801 return retValue; 802 } 803 } 804 getIccFdnAvailable()805 public boolean getIccFdnAvailable() { 806 boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnAvailable() : false; 807 return retValue; 808 } 809 getIccPin2Blocked()810 public boolean getIccPin2Blocked() { 811 /* defaults to disabled */ 812 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPin2Blocked() : false; 813 return retValue; 814 } 815 getIccPuk2Blocked()816 public boolean getIccPuk2Blocked() { 817 /* defaults to disabled */ 818 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPuk2Blocked() : false; 819 return retValue; 820 } 821 822 @Override setIccLockEnabled(boolean enabled, String password, Message onComplete)823 public void setIccLockEnabled(boolean enabled, String password, Message onComplete) { 824 synchronized (mLock) { 825 if (mUiccApplication != null) { 826 mUiccApplication.setIccLockEnabled(enabled, password, onComplete); 827 } else if (onComplete != null) { 828 Exception e = new RuntimeException("ICC card is absent."); 829 AsyncResult.forMessage(onComplete).exception = e; 830 onComplete.sendToTarget(); 831 return; 832 } 833 } 834 } 835 836 @Override setIccFdnEnabled(boolean enabled, String password, Message onComplete)837 public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) { 838 synchronized (mLock) { 839 if (mUiccApplication != null) { 840 mUiccApplication.setIccFdnEnabled(enabled, password, onComplete); 841 } else if (onComplete != null) { 842 Exception e = new RuntimeException("ICC card is absent."); 843 AsyncResult.forMessage(onComplete).exception = e; 844 onComplete.sendToTarget(); 845 return; 846 } 847 } 848 } 849 850 @Override changeIccLockPassword(String oldPassword, String newPassword, Message onComplete)851 public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) { 852 synchronized (mLock) { 853 if (mUiccApplication != null) { 854 mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete); 855 } else if (onComplete != null) { 856 Exception e = new RuntimeException("ICC card is absent."); 857 AsyncResult.forMessage(onComplete).exception = e; 858 onComplete.sendToTarget(); 859 return; 860 } 861 } 862 } 863 864 @Override changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete)865 public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) { 866 synchronized (mLock) { 867 if (mUiccApplication != null) { 868 mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete); 869 } else if (onComplete != null) { 870 Exception e = new RuntimeException("ICC card is absent."); 871 AsyncResult.forMessage(onComplete).exception = e; 872 onComplete.sendToTarget(); 873 return; 874 } 875 } 876 } 877 878 @Override getServiceProviderName()879 public String getServiceProviderName() { 880 synchronized (mLock) { 881 if (mIccRecords != null) { 882 return mIccRecords.getServiceProviderName(); 883 } 884 return null; 885 } 886 } 887 888 @Override isApplicationOnIcc(IccCardApplicationStatus.AppType type)889 public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) { 890 synchronized (mLock) { 891 Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false; 892 return retValue; 893 } 894 } 895 896 @Override hasIccCard()897 public boolean hasIccCard() { 898 synchronized (mLock) { 899 if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) { 900 return true; 901 } 902 return false; 903 } 904 } 905 setSystemProperty(String property, String value)906 private void setSystemProperty(String property, String value) { 907 TelephonyManager.setTelephonyProperty(mPhoneId, property, value); 908 } 909 getIccRecord()910 public IccRecords getIccRecord() { 911 return mIccRecords; 912 } log(String s)913 private void log(String s) { 914 Rlog.d(LOG_TAG, s); 915 } 916 loge(String msg)917 private void loge(String msg) { 918 Rlog.e(LOG_TAG, msg); 919 } 920 dump(FileDescriptor fd, PrintWriter pw, String[] args)921 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 922 pw.println("IccCardProxy: " + this); 923 pw.println(" mContext=" + mContext); 924 pw.println(" mCi=" + mCi); 925 pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size()); 926 for (int i = 0; i < mAbsentRegistrants.size(); i++) { 927 pw.println(" mAbsentRegistrants[" + i + "]=" 928 + ((Registrant)mAbsentRegistrants.get(i)).getHandler()); 929 } 930 pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size()); 931 for (int i = 0; i < mPinLockedRegistrants.size(); i++) { 932 pw.println(" mPinLockedRegistrants[" + i + "]=" 933 + ((Registrant)mPinLockedRegistrants.get(i)).getHandler()); 934 } 935 pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size()); 936 for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) { 937 pw.println(" mNetworkLockedRegistrants[" + i + "]=" 938 + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler()); 939 } 940 pw.println(" mCurrentAppType=" + mCurrentAppType); 941 pw.println(" mUiccController=" + mUiccController); 942 pw.println(" mUiccCard=" + mUiccCard); 943 pw.println(" mUiccApplication=" + mUiccApplication); 944 pw.println(" mIccRecords=" + mIccRecords); 945 pw.println(" mCdmaSSM=" + mCdmaSSM); 946 pw.println(" mRadioOn=" + mRadioOn); 947 pw.println(" mQuietMode=" + mQuietMode); 948 pw.println(" mInitialized=" + mInitialized); 949 pw.println(" mExternalState=" + mExternalState); 950 951 pw.flush(); 952 } 953 } 954