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