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