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