Home | History | Annotate | Download | only in uicc
      1 /*
      2  * Copyright (C) 2006, 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 android.content.Context;
     20 import android.os.AsyncResult;
     21 import android.os.Handler;
     22 import android.os.Message;
     23 import android.os.Registrant;
     24 import android.os.RegistrantList;
     25 import android.telephony.Rlog;
     26 
     27 import com.android.internal.telephony.CommandsInterface;
     28 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
     29 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
     30 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
     31 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
     32 
     33 import java.io.FileDescriptor;
     34 import java.io.PrintWriter;
     35 
     36 /**
     37  * {@hide}
     38  */
     39 public class UiccCardApplication {
     40     private static final String LOG_TAG = "UiccCardApplication";
     41     private static final boolean DBG = true;
     42 
     43     private static final int EVENT_QUERY_FACILITY_FDN_DONE = 1;
     44     private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 2;
     45     private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 3;
     46     private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 4;
     47 
     48     private final Object  mLock = new Object();
     49     private UiccCard      mUiccCard; //parent
     50     private AppState      mAppState;
     51     private AppType       mAppType;
     52     private PersoSubState mPersoSubState;
     53     private String        mAid;
     54     private String        mAppLabel;
     55     private boolean       mPin1Replaced;
     56     private PinState      mPin1State;
     57     private PinState      mPin2State;
     58     private boolean       mIccFdnEnabled;
     59     private boolean       mDesiredFdnEnabled;
     60     private boolean       mIccLockEnabled;
     61     private boolean       mDesiredPinLocked;
     62 
     63     private CommandsInterface mCi;
     64     private Context mContext;
     65     private IccRecords mIccRecords;
     66     private IccFileHandler mIccFh;
     67 
     68     private boolean mDestroyed;//set to true once this App is commanded to be disposed of.
     69 
     70     private RegistrantList mReadyRegistrants = new RegistrantList();
     71     private RegistrantList mPinLockedRegistrants = new RegistrantList();
     72     private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
     73 
     74     UiccCardApplication(UiccCard uiccCard,
     75                         IccCardApplicationStatus as,
     76                         Context c,
     77                         CommandsInterface ci) {
     78         if (DBG) log("Creating UiccApp: " + as);
     79         mUiccCard = uiccCard;
     80         mAppState = as.app_state;
     81         mAppType = as.app_type;
     82         mPersoSubState = as.perso_substate;
     83         mAid = as.aid;
     84         mAppLabel = as.app_label;
     85         mPin1Replaced = (as.pin1_replaced != 0);
     86         mPin1State = as.pin1;
     87         mPin2State = as.pin2;
     88 
     89         mContext = c;
     90         mCi = ci;
     91 
     92         mIccFh = createIccFileHandler(as.app_type);
     93         mIccRecords = createIccRecords(as.app_type, mContext, mCi);
     94         if (mAppState == AppState.APPSTATE_READY) {
     95             queryFdn();
     96             queryPin1State();
     97         }
     98     }
     99 
    100     void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) {
    101         synchronized (mLock) {
    102             if (mDestroyed) {
    103                 loge("Application updated after destroyed! Fix me!");
    104                 return;
    105             }
    106 
    107             if (DBG) log(mAppType + " update. New " + as);
    108             mContext = c;
    109             mCi = ci;
    110             AppType oldAppType = mAppType;
    111             AppState oldAppState = mAppState;
    112             PersoSubState oldPersoSubState = mPersoSubState;
    113             mAppType = as.app_type;
    114             mAppState = as.app_state;
    115             mPersoSubState = as.perso_substate;
    116             mAid = as.aid;
    117             mAppLabel = as.app_label;
    118             mPin1Replaced = (as.pin1_replaced != 0);
    119             mPin1State = as.pin1;
    120             mPin2State = as.pin2;
    121 
    122             if (mAppType != oldAppType) {
    123                 if (mIccFh != null) { mIccFh.dispose();}
    124                 if (mIccRecords != null) { mIccRecords.dispose();}
    125                 mIccFh = createIccFileHandler(as.app_type);
    126                 mIccRecords = createIccRecords(as.app_type, c, ci);
    127             }
    128 
    129             if (mPersoSubState != oldPersoSubState &&
    130                     mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
    131                 notifyNetworkLockedRegistrantsIfNeeded(null);
    132             }
    133 
    134             if (mAppState != oldAppState) {
    135                 if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState);
    136                 // If the app state turns to APPSTATE_READY, then query FDN status,
    137                 //as it might have failed in earlier attempt.
    138                 if (mAppState == AppState.APPSTATE_READY) {
    139                     queryFdn();
    140                     queryPin1State();
    141                 }
    142                 notifyPinLockedRegistrantsIfNeeded(null);
    143                 notifyReadyRegistrantsIfNeeded(null);
    144             }
    145         }
    146     }
    147 
    148     void dispose() {
    149         synchronized (mLock) {
    150             if (DBG) log(mAppType + " being Disposed");
    151             mDestroyed = true;
    152             if (mIccRecords != null) { mIccRecords.dispose();}
    153             if (mIccFh != null) { mIccFh.dispose();}
    154             mIccRecords = null;
    155             mIccFh = null;
    156         }
    157     }
    158 
    159     private IccRecords createIccRecords(AppType type, Context c, CommandsInterface ci) {
    160         if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) {
    161             return new SIMRecords(this, c, ci);
    162         } else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){
    163             return new RuimRecords(this, c, ci);
    164         } else if (type == AppType.APPTYPE_ISIM) {
    165             return new IsimUiccRecords(this, c, ci);
    166         } else {
    167             // Unknown app type (maybe detection is still in progress)
    168             return null;
    169         }
    170     }
    171 
    172     private IccFileHandler createIccFileHandler(AppType type) {
    173         switch (type) {
    174             case APPTYPE_SIM:
    175                 return new SIMFileHandler(this, mAid, mCi);
    176             case APPTYPE_RUIM:
    177                 return new RuimFileHandler(this, mAid, mCi);
    178             case APPTYPE_USIM:
    179                 return new UsimFileHandler(this, mAid, mCi);
    180             case APPTYPE_CSIM:
    181                 return new CsimFileHandler(this, mAid, mCi);
    182             case APPTYPE_ISIM:
    183                 return new IsimFileHandler(this, mAid, mCi);
    184             default:
    185                 return null;
    186         }
    187     }
    188 
    189     /** Assumes mLock is held. */
    190     private void queryFdn() {
    191         //This shouldn't change run-time. So needs to be called only once.
    192         int serviceClassX;
    193 
    194         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
    195                         CommandsInterface.SERVICE_CLASS_DATA +
    196                         CommandsInterface.SERVICE_CLASS_FAX;
    197         mCi.queryFacilityLockForApp (
    198                 CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX,
    199                 mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
    200     }
    201     /**
    202      * Interpret EVENT_QUERY_FACILITY_LOCK_DONE
    203      * @param ar is asyncResult of Query_Facility_Locked
    204      */
    205     private void onQueryFdnEnabled(AsyncResult ar) {
    206         synchronized (mLock) {
    207             if (ar.exception != null) {
    208                 if (DBG) log("Error in querying facility lock:" + ar.exception);
    209                 return;
    210             }
    211 
    212             int[] ints = (int[])ar.result;
    213             if(ints.length != 0) {
    214                 mIccFdnEnabled = (0!=ints[0]);
    215                 if (DBG) log("Query facility lock : "  + mIccFdnEnabled);
    216             } else {
    217                 loge("Bogus facility lock response");
    218             }
    219         }
    220     }
    221 
    222     private void onChangeFdnDone(AsyncResult ar) {
    223         synchronized (mLock) {
    224             if (ar.exception == null) {
    225                 mIccFdnEnabled = mDesiredFdnEnabled;
    226                 if (DBG) log("EVENT_CHANGE_FACILITY_FDN_DONE: " +
    227                         "mIccFdnEnabled=" + mIccFdnEnabled);
    228             } else {
    229                 loge("Error change facility fdn with exception " + ar.exception);
    230             }
    231             Message response = (Message)ar.userObj;
    232             AsyncResult.forMessage(response).exception = ar.exception;
    233             response.sendToTarget();
    234         }
    235     }
    236 
    237     /** REMOVE when mIccLockEnabled is not needed, assumes mLock is held */
    238     private void queryPin1State() {
    239         int serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
    240                 CommandsInterface.SERVICE_CLASS_DATA +
    241                 CommandsInterface.SERVICE_CLASS_FAX;
    242         mCi.queryFacilityLockForApp (
    243             CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
    244             mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
    245     }
    246 
    247     /** REMOVE when mIccLockEnabled is not needed*/
    248     private void onQueryFacilityLock(AsyncResult ar) {
    249         synchronized (mLock) {
    250             if(ar.exception != null) {
    251                 if (DBG) log("Error in querying facility lock:" + ar.exception);
    252                 return;
    253             }
    254 
    255             int[] ints = (int[])ar.result;
    256             if(ints.length != 0) {
    257                 if (DBG) log("Query facility lock : "  + ints[0]);
    258 
    259                 mIccLockEnabled = (ints[0] != 0);
    260 
    261                 if (mIccLockEnabled) {
    262                     mPinLockedRegistrants.notifyRegistrants();
    263                 }
    264 
    265                 // Sanity check: we expect mPin1State to match mIccLockEnabled.
    266                 // When mPin1State is DISABLED mIccLockEanbled should be false.
    267                 // When mPin1State is ENABLED mIccLockEnabled should be true.
    268                 //
    269                 // Here we validate these assumptions to assist in identifying which ril/radio's
    270                 // have not correctly implemented GET_SIM_STATUS
    271                 switch (mPin1State) {
    272                     case PINSTATE_DISABLED:
    273                         if (mIccLockEnabled) {
    274                             loge("QUERY_FACILITY_LOCK:enabled GET_SIM_STATUS.Pin1:disabled."
    275                                     + " Fixme");
    276                         }
    277                         break;
    278                     case PINSTATE_ENABLED_NOT_VERIFIED:
    279                     case PINSTATE_ENABLED_VERIFIED:
    280                     case PINSTATE_ENABLED_BLOCKED:
    281                     case PINSTATE_ENABLED_PERM_BLOCKED:
    282                         if (!mIccLockEnabled) {
    283                             loge("QUERY_FACILITY_LOCK:disabled GET_SIM_STATUS.Pin1:enabled."
    284                                     + " Fixme");
    285                         }
    286                     case PINSTATE_UNKNOWN:
    287                     default:
    288                         if (DBG) log("Ignoring: pin1state=" + mPin1State);
    289                         break;
    290                 }
    291             } else {
    292                 loge("Bogus facility lock response");
    293             }
    294         }
    295     }
    296 
    297     /** REMOVE when mIccLockEnabled is not needed */
    298     private void onChangeFacilityLock(AsyncResult ar) {
    299         synchronized (mLock) {
    300             if (ar.exception == null) {
    301                 mIccLockEnabled = mDesiredPinLocked;
    302                 if (DBG) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: mIccLockEnabled= "
    303                         + mIccLockEnabled);
    304             } else {
    305                 loge("Error change facility lock with exception " + ar.exception);
    306             }
    307             AsyncResult.forMessage(((Message)ar.userObj)).exception = ar.exception;
    308             ((Message)ar.userObj).sendToTarget();
    309         }
    310     }
    311 
    312     private Handler mHandler = new Handler() {
    313         @Override
    314         public void handleMessage(Message msg){
    315             AsyncResult ar;
    316 
    317             if (mDestroyed) {
    318                 loge("Received message " + msg + "[" + msg.what
    319                         + "] while being destroyed. Ignoring.");
    320                 return;
    321             }
    322 
    323             switch (msg.what) {
    324                 case EVENT_QUERY_FACILITY_FDN_DONE:
    325                     ar = (AsyncResult)msg.obj;
    326                     onQueryFdnEnabled(ar);
    327                     break;
    328                 case EVENT_CHANGE_FACILITY_FDN_DONE:
    329                     ar = (AsyncResult)msg.obj;
    330                     onChangeFdnDone(ar);
    331                     break;
    332                 case EVENT_QUERY_FACILITY_LOCK_DONE:
    333                     ar = (AsyncResult)msg.obj;
    334                     onQueryFacilityLock(ar);
    335                     break;
    336                 case EVENT_CHANGE_FACILITY_LOCK_DONE:
    337                     ar = (AsyncResult)msg.obj;
    338                     onChangeFacilityLock(ar);
    339                     break;
    340                 default:
    341                     loge("Unknown Event " + msg.what);
    342             }
    343         }
    344     };
    345 
    346     public void registerForReady(Handler h, int what, Object obj) {
    347         synchronized (mLock) {
    348             Registrant r = new Registrant (h, what, obj);
    349             mReadyRegistrants.add(r);
    350             notifyReadyRegistrantsIfNeeded(r);
    351         }
    352     }
    353 
    354     public void unregisterForReady(Handler h) {
    355         synchronized (mLock) {
    356             mReadyRegistrants.remove(h);
    357         }
    358     }
    359 
    360     /**
    361      * Notifies handler of any transition into State.isPinLocked()
    362      */
    363     public void registerForLocked(Handler h, int what, Object obj) {
    364         synchronized (mLock) {
    365             Registrant r = new Registrant (h, what, obj);
    366             mPinLockedRegistrants.add(r);
    367             notifyPinLockedRegistrantsIfNeeded(r);
    368         }
    369     }
    370 
    371     public void unregisterForLocked(Handler h) {
    372         synchronized (mLock) {
    373             mPinLockedRegistrants.remove(h);
    374         }
    375     }
    376 
    377     /**
    378      * Notifies handler of any transition into State.NETWORK_LOCKED
    379      */
    380     public void registerForNetworkLocked(Handler h, int what, Object obj) {
    381         synchronized (mLock) {
    382             Registrant r = new Registrant (h, what, obj);
    383             mNetworkLockedRegistrants.add(r);
    384             notifyNetworkLockedRegistrantsIfNeeded(r);
    385         }
    386     }
    387 
    388     public void unregisterForNetworkLocked(Handler h) {
    389         synchronized (mLock) {
    390             mNetworkLockedRegistrants.remove(h);
    391         }
    392     }
    393 
    394     /**
    395      * Notifies specified registrant, assume mLock is held.
    396      *
    397      * @param r Registrant to be notified. If null - all registrants will be notified
    398      */
    399     private void notifyReadyRegistrantsIfNeeded(Registrant r) {
    400         if (mDestroyed) {
    401             return;
    402         }
    403         if (mAppState == AppState.APPSTATE_READY) {
    404             if (mPin1State == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
    405                     mPin1State == PinState.PINSTATE_ENABLED_BLOCKED ||
    406                     mPin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
    407                 loge("Sanity check failed! APPSTATE is ready while PIN1 is not verified!!!");
    408                 // Don't notify if application is in insane state
    409                 return;
    410             }
    411             if (r == null) {
    412                 if (DBG) log("Notifying registrants: READY");
    413                 mReadyRegistrants.notifyRegistrants();
    414             } else {
    415                 if (DBG) log("Notifying 1 registrant: READY");
    416                 r.notifyRegistrant(new AsyncResult(null, null, null));
    417             }
    418         }
    419     }
    420 
    421     /**
    422      * Notifies specified registrant, assume mLock is held.
    423      *
    424      * @param r Registrant to be notified. If null - all registrants will be notified
    425      */
    426     private void notifyPinLockedRegistrantsIfNeeded(Registrant r) {
    427         if (mDestroyed) {
    428             return;
    429         }
    430 
    431         if (mAppState == AppState.APPSTATE_PIN ||
    432                 mAppState == AppState.APPSTATE_PUK) {
    433             if (mPin1State == PinState.PINSTATE_ENABLED_VERIFIED ||
    434                     mPin1State == PinState.PINSTATE_DISABLED) {
    435                 loge("Sanity check failed! APPSTATE is locked while PIN1 is not!!!");
    436                 //Don't notify if application is in insane state
    437                 return;
    438             }
    439             if (r == null) {
    440                 if (DBG) log("Notifying registrants: LOCKED");
    441                 mPinLockedRegistrants.notifyRegistrants();
    442             } else {
    443                 if (DBG) log("Notifying 1 registrant: LOCKED");
    444                 r.notifyRegistrant(new AsyncResult(null, null, null));
    445             }
    446         }
    447     }
    448 
    449     /**
    450      * Notifies specified registrant, assume mLock is held.
    451      *
    452      * @param r Registrant to be notified. If null - all registrants will be notified
    453      */
    454     private void notifyNetworkLockedRegistrantsIfNeeded(Registrant r) {
    455         if (mDestroyed) {
    456             return;
    457         }
    458 
    459         if (mAppState == AppState.APPSTATE_SUBSCRIPTION_PERSO &&
    460                 mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
    461             if (r == null) {
    462                 if (DBG) log("Notifying registrants: NETWORK_LOCKED");
    463                 mNetworkLockedRegistrants.notifyRegistrants();
    464             } else {
    465                 if (DBG) log("Notifying 1 registrant: NETWORK_LOCED");
    466                 r.notifyRegistrant(new AsyncResult(null, null, null));
    467             }
    468         }
    469     }
    470 
    471     public AppState getState() {
    472         synchronized (mLock) {
    473             return mAppState;
    474         }
    475     }
    476 
    477     public AppType getType() {
    478         synchronized (mLock) {
    479             return mAppType;
    480         }
    481     }
    482 
    483     public PersoSubState getPersoSubState() {
    484         synchronized (mLock) {
    485             return mPersoSubState;
    486         }
    487     }
    488 
    489     public String getAid() {
    490         synchronized (mLock) {
    491             return mAid;
    492         }
    493     }
    494 
    495     public PinState getPin1State() {
    496         synchronized (mLock) {
    497             if (mPin1Replaced) {
    498                 return mUiccCard.getUniversalPinState();
    499             }
    500             return mPin1State;
    501         }
    502     }
    503 
    504     public IccFileHandler getIccFileHandler() {
    505         synchronized (mLock) {
    506             return mIccFh;
    507         }
    508     }
    509 
    510     public IccRecords getIccRecords() {
    511         synchronized (mLock) {
    512             return mIccRecords;
    513         }
    514     }
    515 
    516     /**
    517      * Supply the ICC PIN to the ICC
    518      *
    519      * When the operation is complete, onComplete will be sent to its
    520      * Handler.
    521      *
    522      * onComplete.obj will be an AsyncResult
    523      *
    524      * ((AsyncResult)onComplete.obj).exception == null on success
    525      * ((AsyncResult)onComplete.obj).exception != null on fail
    526      *
    527      * If the supplied PIN is incorrect:
    528      * ((AsyncResult)onComplete.obj).exception != null
    529      * && ((AsyncResult)onComplete.obj).exception
    530      *       instanceof com.android.internal.telephony.gsm.CommandException)
    531      * && ((CommandException)(((AsyncResult)onComplete.obj).exception))
    532      *          .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
    533      *
    534      *
    535      */
    536     public void supplyPin (String pin, Message onComplete) {
    537         synchronized (mLock) {
    538             mCi.supplyIccPin(pin, onComplete);
    539         }
    540     }
    541 
    542     public void supplyPuk (String puk, String newPin, Message onComplete) {
    543         synchronized (mLock) {
    544             mCi.supplyIccPuk(puk, newPin, onComplete);
    545         }
    546     }
    547 
    548     public void supplyPin2 (String pin2, Message onComplete) {
    549         synchronized (mLock) {
    550             mCi.supplyIccPin2(pin2, onComplete);
    551         }
    552     }
    553 
    554     public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
    555         synchronized (mLock) {
    556             mCi.supplyIccPuk2(puk2, newPin2, onComplete);
    557         }
    558     }
    559 
    560     public void supplyNetworkDepersonalization (String pin, Message onComplete) {
    561         synchronized (mLock) {
    562             if (DBG) log("supplyNetworkDepersonalization");
    563             mCi.supplyNetworkDepersonalization(pin, onComplete);
    564         }
    565     }
    566 
    567     /**
    568      * Check whether ICC pin lock is enabled
    569      * This is a sync call which returns the cached pin enabled state
    570      *
    571      * @return true for ICC locked enabled
    572      *         false for ICC locked disabled
    573      */
    574     public boolean getIccLockEnabled() {
    575         return mIccLockEnabled;
    576         /* STOPSHIP: Remove line above and all code associated with setting
    577            mIccLockEanbled once all RIL correctly sends the pin1 state.
    578         // Use getPin1State to take into account pin1Replaced flag
    579         PinState pinState = getPin1State();
    580         return pinState == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
    581                pinState == PinState.PINSTATE_ENABLED_VERIFIED ||
    582                pinState == PinState.PINSTATE_ENABLED_BLOCKED ||
    583                pinState == PinState.PINSTATE_ENABLED_PERM_BLOCKED;*/
    584      }
    585 
    586     /**
    587      * Check whether ICC fdn (fixed dialing number) is enabled
    588      * This is a sync call which returns the cached pin enabled state
    589      *
    590      * @return true for ICC fdn enabled
    591      *         false for ICC fdn disabled
    592      */
    593     public boolean getIccFdnEnabled() {
    594         synchronized (mLock) {
    595             return mIccFdnEnabled;
    596         }
    597     }
    598 
    599     /**
    600      * Set the ICC pin lock enabled or disabled
    601      * When the operation is complete, onComplete will be sent to its handler
    602      *
    603      * @param enabled "true" for locked "false" for unlocked.
    604      * @param password needed to change the ICC pin state, aka. Pin1
    605      * @param onComplete
    606      *        onComplete.obj will be an AsyncResult
    607      *        ((AsyncResult)onComplete.obj).exception == null on success
    608      *        ((AsyncResult)onComplete.obj).exception != null on fail
    609      */
    610     public void setIccLockEnabled (boolean enabled,
    611             String password, Message onComplete) {
    612         synchronized (mLock) {
    613             int serviceClassX;
    614             serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
    615                     CommandsInterface.SERVICE_CLASS_DATA +
    616                     CommandsInterface.SERVICE_CLASS_FAX;
    617 
    618             mDesiredPinLocked = enabled;
    619 
    620             mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_SIM,
    621                     enabled, password, serviceClassX, mAid,
    622                     mHandler.obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
    623         }
    624     }
    625 
    626     /**
    627      * Set the ICC fdn enabled or disabled
    628      * When the operation is complete, onComplete will be sent to its handler
    629      *
    630      * @param enabled "true" for locked "false" for unlocked.
    631      * @param password needed to change the ICC fdn enable, aka Pin2
    632      * @param onComplete
    633      *        onComplete.obj will be an AsyncResult
    634      *        ((AsyncResult)onComplete.obj).exception == null on success
    635      *        ((AsyncResult)onComplete.obj).exception != null on fail
    636      */
    637     public void setIccFdnEnabled (boolean enabled,
    638             String password, Message onComplete) {
    639         synchronized (mLock) {
    640             int serviceClassX;
    641             serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
    642                     CommandsInterface.SERVICE_CLASS_DATA +
    643                     CommandsInterface.SERVICE_CLASS_FAX +
    644                     CommandsInterface.SERVICE_CLASS_SMS;
    645 
    646             mDesiredFdnEnabled = enabled;
    647 
    648             mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_FD,
    649                     enabled, password, serviceClassX, mAid,
    650                     mHandler.obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
    651         }
    652     }
    653 
    654     /**
    655      * Change the ICC password used in ICC pin lock
    656      * When the operation is complete, onComplete will be sent to its handler
    657      *
    658      * @param oldPassword is the old password
    659      * @param newPassword is the new password
    660      * @param onComplete
    661      *        onComplete.obj will be an AsyncResult
    662      *        ((AsyncResult)onComplete.obj).exception == null on success
    663      *        ((AsyncResult)onComplete.obj).exception != null on fail
    664      */
    665     public void changeIccLockPassword(String oldPassword, String newPassword,
    666             Message onComplete) {
    667         synchronized (mLock) {
    668             if (DBG) log("changeIccLockPassword");
    669             mCi.changeIccPinForApp(oldPassword, newPassword, mAid,
    670                     onComplete);
    671         }
    672     }
    673 
    674     /**
    675      * Change the ICC password used in ICC fdn enable
    676      * When the operation is complete, onComplete will be sent to its handler
    677      *
    678      * @param oldPassword is the old password
    679      * @param newPassword is the new password
    680      * @param onComplete
    681      *        onComplete.obj will be an AsyncResult
    682      *        ((AsyncResult)onComplete.obj).exception == null on success
    683      *        ((AsyncResult)onComplete.obj).exception != null on fail
    684      */
    685     public void changeIccFdnPassword(String oldPassword, String newPassword,
    686             Message onComplete) {
    687         synchronized (mLock) {
    688             if (DBG) log("changeIccFdnPassword");
    689             mCi.changeIccPin2ForApp(oldPassword, newPassword, mAid,
    690                     onComplete);
    691         }
    692     }
    693 
    694     private void log(String msg) {
    695         Rlog.d(LOG_TAG, msg);
    696     }
    697 
    698     private void loge(String msg) {
    699         Rlog.e(LOG_TAG, msg);
    700     }
    701 
    702     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    703         pw.println("UiccCardApplication: " + this);
    704         pw.println(" mUiccCard=" + mUiccCard);
    705         pw.println(" mAppState=" + mAppState);
    706         pw.println(" mAppType=" + mAppType);
    707         pw.println(" mPersoSubState=" + mPersoSubState);
    708         pw.println(" mAid=" + mAid);
    709         pw.println(" mAppLabel=" + mAppLabel);
    710         pw.println(" mPin1Replaced=" + mPin1Replaced);
    711         pw.println(" mPin1State=" + mPin1State);
    712         pw.println(" mPin2State=" + mPin2State);
    713         pw.println(" mIccFdnEnabled=" + mIccFdnEnabled);
    714         pw.println(" mDesiredFdnEnabled=" + mDesiredFdnEnabled);
    715         pw.println(" mIccLockEnabled=" + mIccLockEnabled);
    716         pw.println(" mDesiredPinLocked=" + mDesiredPinLocked);
    717         pw.println(" mCi=" + mCi);
    718         pw.println(" mIccRecords=" + mIccRecords);
    719         pw.println(" mIccFh=" + mIccFh);
    720         pw.println(" mDestroyed=" + mDestroyed);
    721         pw.println(" mReadyRegistrants: size=" + mReadyRegistrants.size());
    722         for (int i = 0; i < mReadyRegistrants.size(); i++) {
    723             pw.println("  mReadyRegistrants[" + i + "]="
    724                     + ((Registrant)mReadyRegistrants.get(i)).getHandler());
    725         }
    726         pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size());
    727         for (int i = 0; i < mPinLockedRegistrants.size(); i++) {
    728             pw.println("  mPinLockedRegistrants[" + i + "]="
    729                     + ((Registrant)mPinLockedRegistrants.get(i)).getHandler());
    730         }
    731         pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size());
    732         for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) {
    733             pw.println("  mNetworkLockedRegistrants[" + i + "]="
    734                     + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler());
    735         }
    736         pw.flush();
    737     }
    738 }
    739