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