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