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