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