733af6415e9e08fdde2267d56aae21e724891181
[android/platform/frameworks/opt/telephony.git] / src / java / com / android / internal / telephony / uicc / IccCardProxy.java
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 import android.app.ActivityManagerNative;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.AsyncResult;
24 import android.os.Handler;
25 import android.os.Message;
26 import android.os.Registrant;
27 import android.os.RegistrantList;
28 import android.os.SystemProperties;
29 import android.os.UserHandle;
30 import android.telephony.Rlog;
31 import android.telephony.ServiceState;
32 import android.telephony.TelephonyManager;
33
34 import com.android.internal.telephony.CommandsInterface;
35 import com.android.internal.telephony.IccCard;
36 import com.android.internal.telephony.IccCardConstants;
37 import com.android.internal.telephony.PhoneConstants;
38 import com.android.internal.telephony.RILConstants;
39 import com.android.internal.telephony.TelephonyIntents;
40 import com.android.internal.telephony.IccCardConstants.State;
41 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
42 import com.android.internal.telephony.Phone;
43 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
44 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
45 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
46 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
47 import com.android.internal.telephony.uicc.UiccController;
48
49 import java.io.FileDescriptor;
50 import java.io.PrintWriter;
51
52 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_STATE;
53
54 /**
55  * @Deprecated use {@link UiccController}.getUiccCard instead.
56  *
57  * The Phone App assumes that there is only one icc card, and one icc application
58  * available at a time. Moreover, it assumes such object (represented with IccCard)
59  * is available all the time (whether {@link RILConstants#RIL_REQUEST_GET_SIM_STATUS} returned
60  * or not, whether card has desired application or not, whether there really is a card in the
61  * slot or not).
62  *
63  * UiccController, however, can handle multiple instances of icc objects (multiple
64  * {@link UiccCardApplication}, multiple {@link IccFileHandler}, multiple {@link IccRecords})
65  * created and destroyed dynamically during phone operation.
66  *
67  * This class implements the IccCard interface that is always available (right after default
68  * phone object is constructed) to expose the current (based on voice radio technology)
69  * application on the uicc card, so that external apps won't break.
70  */
71
72 public class IccCardProxy extends Handler implements IccCard {
73     private static final boolean DBG = true;
74     private static final String LOG_TAG = "IccCardProxy";
75
76     private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 1;
77     private static final int EVENT_RADIO_ON = 2;
78     private static final int EVENT_ICC_CHANGED = 3;
79     private static final int EVENT_ICC_ABSENT = 4;
80     private static final int EVENT_ICC_LOCKED = 5;
81     private static final int EVENT_APP_READY = 6;
82     private static final int EVENT_RECORDS_LOADED = 7;
83     private static final int EVENT_IMSI_READY = 8;
84     private static final int EVENT_NETWORK_LOCKED = 9;
85     private static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 11;
86
87     private final Object mLock = new Object();
88     private Context mContext;
89     private CommandsInterface mCi;
90
91     private RegistrantList mAbsentRegistrants = new RegistrantList();
92     private RegistrantList mPinLockedRegistrants = new RegistrantList();
93     private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
94
95     private int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp?
96     private UiccController mUiccController = null;
97     private UiccCard mUiccCard = null;
98     private UiccCardApplication mUiccApplication = null;
99     private IccRecords mIccRecords = null;
100     private CdmaSubscriptionSourceManager mCdmaSSM = null;
101     private boolean mRadioOn = false;
102     private boolean mQuietMode = false; // when set to true IccCardProxy will not broadcast
103                                         // ACTION_SIM_STATE_CHANGED intents
104     private boolean mInitialized = false;
105     private State mExternalState = State.UNKNOWN;
106
107     public IccCardProxy(Context context, CommandsInterface ci) {
108         log("Creating");
109         mContext = context;
110         mCi = ci;
111         mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context,
112                 ci, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
113         mUiccController = UiccController.getInstance();
114         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
115         ci.registerForOn(this,EVENT_RADIO_ON, null);
116         ci.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
117         setExternalState(State.NOT_READY);
118     }
119
120     public void dispose() {
121         synchronized (mLock) {
122             log("Disposing");
123             //Cleanup icc references
124             mUiccController.unregisterForIccChanged(this);
125             mUiccController = null;
126             mCi.unregisterForOn(this);
127             mCi.unregisterForOffOrNotAvailable(this);
128             mCdmaSSM.dispose(this);
129         }
130     }
131
132     /*
133      * The card application that the external world sees will be based on the
134      * voice radio technology only!
135      */
136     public void setVoiceRadioTech(int radioTech) {
137         synchronized (mLock) {
138             if (DBG) {
139                 log("Setting radio tech " + ServiceState.rilRadioTechnologyToString(radioTech));
140             }
141             if (ServiceState.isGsm(radioTech)) {
142                 mCurrentAppType = UiccController.APP_FAM_3GPP;
143             } else {
144                 mCurrentAppType = UiccController.APP_FAM_3GPP2;
145             }
146             updateQuietMode();
147         }
148     }
149
150     /**
151      * In case of 3gpp2 we need to find out if subscription used is coming from
152      * NV in which case we shouldn't broadcast any sim states changes.
153      */
154     private void updateQuietMode() {
155         synchronized (mLock) {
156             boolean oldQuietMode = mQuietMode;
157             boolean newQuietMode;
158             int cdmaSource = Phone.CDMA_SUBSCRIPTION_UNKNOWN;
159             boolean isLteOnCdmaMode = TelephonyManager.getLteOnCdmaModeStatic()
160                     == PhoneConstants.LTE_ON_CDMA_TRUE;
161             if (mCurrentAppType == UiccController.APP_FAM_3GPP) {
162                 newQuietMode = false;
163                 if (DBG) log("updateQuietMode: 3GPP subscription -> newQuietMode=" + newQuietMode);
164             } else {
165                 if (isLteOnCdmaMode) {
166                     log("updateQuietMode: is cdma/lte device, force IccCardProxy into 3gpp mode");
167                     mCurrentAppType = UiccController.APP_FAM_3GPP;
168                 }
169                 cdmaSource = mCdmaSSM != null ?
170                         mCdmaSSM.getCdmaSubscriptionSource() : Phone.CDMA_SUBSCRIPTION_UNKNOWN;
171
172                 newQuietMode = (cdmaSource == Phone.CDMA_SUBSCRIPTION_NV)
173                         && (mCurrentAppType == UiccController.APP_FAM_3GPP2)
174                         && !isLteOnCdmaMode;
175             }
176
177             if (mQuietMode == false && newQuietMode == true) {
178                 // Last thing to do before switching to quiet mode is
179                 // broadcast ICC_READY
180                 log("Switching to QuietMode.");
181                 setExternalState(State.READY);
182                 mQuietMode = newQuietMode;
183             } else if (mQuietMode == true && newQuietMode == false) {
184                 if (DBG) {
185                     log("updateQuietMode: Switching out from QuietMode."
186                             + " Force broadcast of current state=" + mExternalState);
187                 }
188                 mQuietMode = newQuietMode;
189                 setExternalState(mExternalState, true);
190             }
191             if (DBG) {
192                 log("updateQuietMode: QuietMode is " + mQuietMode + " (app_type="
193                     + mCurrentAppType + " isLteOnCdmaMode=" + isLteOnCdmaMode
194                     + " cdmaSource=" + cdmaSource + ")");
195             }
196             mInitialized = true;
197             sendMessage(obtainMessage(EVENT_ICC_CHANGED));
198         }
199     }
200
201     @Override
202     public void handleMessage(Message msg) {
203         switch (msg.what) {
204             case EVENT_RADIO_OFF_OR_UNAVAILABLE:
205                 mRadioOn = false;
206                 break;
207             case EVENT_RADIO_ON:
208                 mRadioOn = true;
209                 if (!mInitialized) {
210                     updateQuietMode();
211                 }
212                 break;
213             case EVENT_ICC_CHANGED:
214                 if (mInitialized) {
215                     updateIccAvailability();
216                 }
217                 break;
218             case EVENT_ICC_ABSENT:
219                 mAbsentRegistrants.notifyRegistrants();
220                 setExternalState(State.ABSENT);
221                 break;
222             case EVENT_ICC_LOCKED:
223                 processLockedState();
224                 break;
225             case EVENT_APP_READY:
226                 setExternalState(State.READY);
227                 break;
228             case EVENT_RECORDS_LOADED:
229                 broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
230                 break;
231             case EVENT_IMSI_READY:
232                 broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_IMSI, null);
233                 break;
234             case EVENT_NETWORK_LOCKED:
235                 mNetworkLockedRegistrants.notifyRegistrants();
236                 setExternalState(State.NETWORK_LOCKED);
237                 break;
238             case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
239                 updateQuietMode();
240                 break;
241             default:
242                 loge("Unhandled message with number: " + msg.what);
243                 break;
244         }
245     }
246
247     private void updateIccAvailability() {
248         synchronized (mLock) {
249             UiccCard newCard = mUiccController.getUiccCard();
250             CardState state = CardState.CARDSTATE_ABSENT;
251             UiccCardApplication newApp = null;
252             IccRecords newRecords = null;
253             if (newCard != null) {
254                 state = newCard.getCardState();
255                 newApp = newCard.getApplication(mCurrentAppType);
256                 if (newApp != null) {
257                     newRecords = newApp.getIccRecords();
258                 }
259             }
260
261             if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) {
262                 if (DBG) log("Icc changed. Reregestering.");
263                 unregisterUiccCardEvents();
264                 mUiccCard = newCard;
265                 mUiccApplication = newApp;
266                 mIccRecords = newRecords;
267                 registerUiccCardEvents();
268             }
269
270             updateExternalState();
271         }
272     }
273
274     private void updateExternalState() {
275         if (mUiccCard == null || mUiccCard.getCardState() == CardState.CARDSTATE_ABSENT) {
276             if (mRadioOn) {
277                 setExternalState(State.ABSENT);
278             } else {
279                 setExternalState(State.NOT_READY);
280             }
281             return;
282         }
283
284         if (mUiccCard.getCardState() == CardState.CARDSTATE_ERROR ||
285                 mUiccApplication == null) {
286             setExternalState(State.UNKNOWN);
287             return;
288         }
289
290         switch (mUiccApplication.getState()) {
291             case APPSTATE_UNKNOWN:
292             case APPSTATE_DETECTED:
293                 setExternalState(State.UNKNOWN);
294                 break;
295             case APPSTATE_PIN:
296                 setExternalState(State.PIN_REQUIRED);
297                 break;
298             case APPSTATE_PUK:
299                 setExternalState(State.PUK_REQUIRED);
300                 break;
301             case APPSTATE_SUBSCRIPTION_PERSO:
302                 if (mUiccApplication.getPersoSubState() == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
303                     setExternalState(State.NETWORK_LOCKED);
304                 } else {
305                     setExternalState(State.UNKNOWN);
306                 }
307                 break;
308             case APPSTATE_READY:
309                 setExternalState(State.READY);
310                 break;
311         }
312     }
313
314     private void registerUiccCardEvents() {
315         if (mUiccCard != null) mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null);
316         if (mUiccApplication != null) {
317             mUiccApplication.registerForReady(this, EVENT_APP_READY, null);
318             mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null);
319             mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null);
320         }
321         if (mIccRecords != null) {
322             mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null);
323             mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
324         }
325     }
326
327     private void unregisterUiccCardEvents() {
328         if (mUiccCard != null) mUiccCard.unregisterForAbsent(this);
329         if (mUiccApplication != null) mUiccApplication.unregisterForReady(this);
330         if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this);
331         if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this);
332         if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this);
333         if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this);
334     }
335
336     private void broadcastIccStateChangedIntent(String value, String reason) {
337         synchronized (mLock) {
338             if (mQuietMode) {
339                 log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " +  value
340                         + " reason " + reason);
341                 return;
342             }
343
344             Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
345             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
346             intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
347             intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
348             intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
349
350             if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " +  value
351                     + " reason " + reason);
352             ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE,
353                     UserHandle.USER_ALL);
354         }
355     }
356
357     private void processLockedState() {
358         synchronized (mLock) {
359             if (mUiccApplication == null) {
360                 //Don't need to do anything if non-existent application is locked
361                 return;
362             }
363             PinState pin1State = mUiccApplication.getPin1State();
364             if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
365                 setExternalState(State.PERM_DISABLED);
366                 return;
367             }
368
369             AppState appState = mUiccApplication.getState();
370             switch (appState) {
371                 case APPSTATE_PIN:
372                     mPinLockedRegistrants.notifyRegistrants();
373                     setExternalState(State.PIN_REQUIRED);
374                     break;
375                 case APPSTATE_PUK:
376                     setExternalState(State.PUK_REQUIRED);
377                     break;
378                 case APPSTATE_DETECTED:
379                 case APPSTATE_READY:
380                 case APPSTATE_SUBSCRIPTION_PERSO:
381                 case APPSTATE_UNKNOWN:
382                     // Neither required
383                     break;
384             }
385         }
386     }
387
388     private void setExternalState(State newState, boolean override) {
389         synchronized (mLock) {
390             if (!override && newState == mExternalState) {
391                 return;
392             }
393             mExternalState = newState;
394             SystemProperties.set(PROPERTY_SIM_STATE, mExternalState.toString());
395             broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState),
396                     getIccStateReason(mExternalState));
397         }
398     }
399
400     private void setExternalState(State newState) {
401         setExternalState(newState, false);
402     }
403
404     public boolean getIccRecordsLoaded() {
405         synchronized (mLock) {
406             if (mIccRecords != null) {
407                 return mIccRecords.getRecordsLoaded();
408             }
409             return false;
410         }
411     }
412
413     private String getIccStateIntentString(State state) {
414         switch (state) {
415             case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT;
416             case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
417             case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
418             case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
419             case READY: return IccCardConstants.INTENT_VALUE_ICC_READY;
420             case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY;
421             case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
422             default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN;
423         }
424     }
425
426     /**
427      * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED)
428      * @return reason
429      */
430     private String getIccStateReason(State state) {
431         switch (state) {
432             case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN;
433             case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK;
434             case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK;
435             case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED;
436             default: return null;
437        }
438     }
439
440     /* IccCard interface implementation */
441     @Override
442     public State getState() {
443         synchronized (mLock) {
444             return mExternalState;
445         }
446     }
447
448     @Override
449     public IccRecords getIccRecords() {
450         synchronized (mLock) {
451             return mIccRecords;
452         }
453     }
454
455     @Override
456     public IccFileHandler getIccFileHandler() {
457         synchronized (mLock) {
458             if (mUiccApplication != null) {
459                 return mUiccApplication.getIccFileHandler();
460             }
461             return null;
462         }
463     }
464
465     /**
466      * Notifies handler of any transition into State.ABSENT
467      */
468     @Override
469     public void registerForAbsent(Handler h, int what, Object obj) {
470         synchronized (mLock) {
471             Registrant r = new Registrant (h, what, obj);
472
473             mAbsentRegistrants.add(r);
474
475             if (getState() == State.ABSENT) {
476                 r.notifyRegistrant();
477             }
478         }
479     }
480
481     @Override
482     public void unregisterForAbsent(Handler h) {
483         synchronized (mLock) {
484             mAbsentRegistrants.remove(h);
485         }
486     }
487
488     /**
489      * Notifies handler of any transition into State.NETWORK_LOCKED
490      */
491     @Override
492     public void registerForNetworkLocked(Handler h, int what, Object obj) {
493         synchronized (mLock) {
494             Registrant r = new Registrant (h, what, obj);
495
496             mNetworkLockedRegistrants.add(r);
497
498             if (getState() == State.NETWORK_LOCKED) {
499                 r.notifyRegistrant();
500             }
501         }
502     }
503
504     @Override
505     public void unregisterForNetworkLocked(Handler h) {
506         synchronized (mLock) {
507             mNetworkLockedRegistrants.remove(h);
508         }
509     }
510
511     /**
512      * Notifies handler of any transition into State.isPinLocked()
513      */
514     @Override
515     public void registerForLocked(Handler h, int what, Object obj) {
516         synchronized (mLock) {
517             Registrant r = new Registrant (h, what, obj);
518
519             mPinLockedRegistrants.add(r);
520
521             if (getState().isPinLocked()) {
522                 r.notifyRegistrant();
523             }
524         }
525     }
526
527     @Override
528     public void unregisterForLocked(Handler h) {
529         synchronized (mLock) {
530             mPinLockedRegistrants.remove(h);
531         }
532     }
533
534     @Override
535     public void supplyPin(String pin, Message onComplete) {
536         synchronized (mLock) {
537             if (mUiccApplication != null) {
538                 mUiccApplication.supplyPin(pin, onComplete);
539             } else if (onComplete != null) {
540                 Exception e = new RuntimeException("ICC card is absent.");
541                 AsyncResult.forMessage(onComplete).exception = e;
542                 onComplete.sendToTarget();
543                 return;
544             }
545         }
546     }
547
548     @Override
549     public void supplyPuk(String puk, String newPin, Message onComplete) {
550         synchronized (mLock) {
551             if (mUiccApplication != null) {
552                 mUiccApplication.supplyPuk(puk, newPin, onComplete);
553             } else if (onComplete != null) {
554                 Exception e = new RuntimeException("ICC card is absent.");
555                 AsyncResult.forMessage(onComplete).exception = e;
556                 onComplete.sendToTarget();
557                 return;
558             }
559         }
560     }
561
562     @Override
563     public void supplyPin2(String pin2, Message onComplete) {
564         synchronized (mLock) {
565             if (mUiccApplication != null) {
566                 mUiccApplication.supplyPin2(pin2, onComplete);
567             } else if (onComplete != null) {
568                 Exception e = new RuntimeException("ICC card is absent.");
569                 AsyncResult.forMessage(onComplete).exception = e;
570                 onComplete.sendToTarget();
571                 return;
572             }
573         }
574     }
575
576     @Override
577     public void supplyPuk2(String puk2, String newPin2, Message onComplete) {
578         synchronized (mLock) {
579             if (mUiccApplication != null) {
580                 mUiccApplication.supplyPuk2(puk2, newPin2, onComplete);
581             } else if (onComplete != null) {
582                 Exception e = new RuntimeException("ICC card is absent.");
583                 AsyncResult.forMessage(onComplete).exception = e;
584                 onComplete.sendToTarget();
585                 return;
586             }
587         }
588     }
589
590     @Override
591     public void supplyNetworkDepersonalization(String pin, Message onComplete) {
592         synchronized (mLock) {
593             if (mUiccApplication != null) {
594                 mUiccApplication.supplyNetworkDepersonalization(pin, onComplete);
595             } else if (onComplete != null) {
596                 Exception e = new RuntimeException("CommandsInterface is not set.");
597                 AsyncResult.forMessage(onComplete).exception = e;
598                 onComplete.sendToTarget();
599                 return;
600             }
601         }
602     }
603
604     @Override
605     public boolean getIccLockEnabled() {
606         synchronized (mLock) {
607             /* defaults to true, if ICC is absent */
608             Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccLockEnabled() : true;
609             return retValue;
610         }
611     }
612
613     @Override
614     public boolean getIccFdnEnabled() {
615         synchronized (mLock) {
616             Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnEnabled() : false;
617             return retValue;
618         }
619     }
620
621     @Override
622     public void setIccLockEnabled(boolean enabled, String password, Message onComplete) {
623         synchronized (mLock) {
624             if (mUiccApplication != null) {
625                 mUiccApplication.setIccLockEnabled(enabled, password, onComplete);
626             } else if (onComplete != null) {
627                 Exception e = new RuntimeException("ICC card is absent.");
628                 AsyncResult.forMessage(onComplete).exception = e;
629                 onComplete.sendToTarget();
630                 return;
631             }
632         }
633     }
634
635     @Override
636     public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) {
637         synchronized (mLock) {
638             if (mUiccApplication != null) {
639                 mUiccApplication.setIccFdnEnabled(enabled, password, onComplete);
640             } else if (onComplete != null) {
641                 Exception e = new RuntimeException("ICC card is absent.");
642                 AsyncResult.forMessage(onComplete).exception = e;
643                 onComplete.sendToTarget();
644                 return;
645             }
646         }
647     }
648
649     @Override
650     public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) {
651         synchronized (mLock) {
652             if (mUiccApplication != null) {
653                 mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete);
654             } else if (onComplete != null) {
655                 Exception e = new RuntimeException("ICC card is absent.");
656                 AsyncResult.forMessage(onComplete).exception = e;
657                 onComplete.sendToTarget();
658                 return;
659             }
660         }
661     }
662
663     @Override
664     public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) {
665         synchronized (mLock) {
666             if (mUiccApplication != null) {
667                 mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete);
668             } else if (onComplete != null) {
669                 Exception e = new RuntimeException("ICC card is absent.");
670                 AsyncResult.forMessage(onComplete).exception = e;
671                 onComplete.sendToTarget();
672                 return;
673             }
674         }
675     }
676
677     @Override
678     public String getServiceProviderName() {
679         synchronized (mLock) {
680             if (mIccRecords != null) {
681                 return mIccRecords.getServiceProviderName();
682             }
683             return null;
684         }
685     }
686
687     @Override
688     public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
689         synchronized (mLock) {
690             Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false;
691             return retValue;
692         }
693     }
694
695     @Override
696     public boolean hasIccCard() {
697         synchronized (mLock) {
698             if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) {
699                 return true;
700             }
701             return false;
702         }
703     }
704
705     private void log(String s) {
706         Rlog.d(LOG_TAG, s);
707     }
708
709     private void loge(String msg) {
710         Rlog.e(LOG_TAG, msg);
711     }
712
713     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
714         pw.println("IccCardProxy: " + this);
715         pw.println(" mContext=" + mContext);
716         pw.println(" mCi=" + mCi);
717         pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size());
718         for (int i = 0; i < mAbsentRegistrants.size(); i++) {
719             pw.println("  mAbsentRegistrants[" + i + "]="
720                     + ((Registrant)mAbsentRegistrants.get(i)).getHandler());
721         }
722         pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size());
723         for (int i = 0; i < mPinLockedRegistrants.size(); i++) {
724             pw.println("  mPinLockedRegistrants[" + i + "]="
725                     + ((Registrant)mPinLockedRegistrants.get(i)).getHandler());
726         }
727         pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size());
728         for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) {
729             pw.println("  mNetworkLockedRegistrants[" + i + "]="
730                     + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler());
731         }
732         pw.println(" mCurrentAppType=" + mCurrentAppType);
733         pw.println(" mUiccController=" + mUiccController);
734         pw.println(" mUiccCard=" + mUiccCard);
735         pw.println(" mUiccApplication=" + mUiccApplication);
736         pw.println(" mIccRecords=" + mIccRecords);
737         pw.println(" mCdmaSSM=" + mCdmaSSM);
738         pw.println(" mRadioOn=" + mRadioOn);
739         pw.println(" mQuietMode=" + mQuietMode);
740         pw.println(" mInitialized=" + mInitialized);
741         pw.println(" mExternalState=" + mExternalState);
742
743         pw.flush();
744     }
745 }