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