SimulatedCommands.java revision a63f55cf17629426d976830429a7612387532195
1/*
2 * Copyright (C) 2006 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
17package com.android.internal.telephony.test;
18
19import android.os.AsyncResult;
20import android.os.HandlerThread;
21import android.os.Looper;
22import android.os.Message;
23import android.telephony.Rlog;
24
25import com.android.internal.telephony.BaseCommands;
26import com.android.internal.telephony.CommandException;
27import com.android.internal.telephony.CommandsInterface;
28import com.android.internal.telephony.DataCallState;
29import com.android.internal.telephony.Phone;
30import com.android.internal.telephony.UUSInfo;
31import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
32import com.android.internal.telephony.gsm.CallFailCause;
33import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
34import com.android.internal.telephony.gsm.SuppServiceNotification;
35
36import java.util.ArrayList;
37
38public final class SimulatedCommands extends BaseCommands
39        implements CommandsInterface, SimulatedRadioControl {
40    private final static String LOG_TAG = "SIM";
41
42    private enum SimLockState {
43        NONE,
44        REQUIRE_PIN,
45        REQUIRE_PUK,
46        SIM_PERM_LOCKED
47    }
48
49    private enum SimFdnState {
50        NONE,
51        REQUIRE_PIN2,
52        REQUIRE_PUK2,
53        SIM_PERM_LOCKED
54    }
55
56    private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE;
57    private final static String DEFAULT_SIM_PIN_CODE = "1234";
58    private final static String SIM_PUK_CODE = "12345678";
59    private final static SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE;
60    private final static String DEFAULT_SIM_PIN2_CODE = "5678";
61    private final static String SIM_PUK2_CODE = "87654321";
62
63    //***** Instance Variables
64
65    SimulatedGsmCallState simulatedCallState;
66    HandlerThread mHandlerThread;
67    SimLockState mSimLockedState;
68    boolean mSimLockEnabled;
69    int mPinUnlockAttempts;
70    int mPukUnlockAttempts;
71    String mPinCode;
72    SimFdnState mSimFdnEnabledState;
73    boolean mSimFdnEnabled;
74    int mPin2UnlockAttempts;
75    int mPuk2UnlockAttempts;
76    int mNetworkType;
77    String mPin2Code;
78    boolean mSsnNotifyOn = false;
79
80    int pausedResponseCount;
81    ArrayList<Message> pausedResponses = new ArrayList<Message>();
82
83    int nextCallFailCause = CallFailCause.NORMAL_CLEARING;
84
85    //***** Constructor
86
87    public
88    SimulatedCommands() {
89        super(null);  // Don't log statistics
90        mHandlerThread = new HandlerThread("SimulatedCommands");
91        mHandlerThread.start();
92        Looper looper = mHandlerThread.getLooper();
93
94        simulatedCallState = new SimulatedGsmCallState(looper);
95
96        setRadioState(RadioState.RADIO_OFF);
97        mSimLockedState = INITIAL_LOCK_STATE;
98        mSimLockEnabled = (mSimLockedState != SimLockState.NONE);
99        mPinCode = DEFAULT_SIM_PIN_CODE;
100        mSimFdnEnabledState = INITIAL_FDN_STATE;
101        mSimFdnEnabled = (mSimFdnEnabledState != SimFdnState.NONE);
102        mPin2Code = DEFAULT_SIM_PIN2_CODE;
103    }
104
105    //***** CommandsInterface implementation
106
107    public void getIccCardStatus(Message result) {
108        unimplemented(result);
109    }
110
111    public void supplyIccPin(String pin, Message result)  {
112        if (mSimLockedState != SimLockState.REQUIRE_PIN) {
113            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: wrong state, state=" +
114                    mSimLockedState);
115            CommandException ex = new CommandException(
116                    CommandException.Error.PASSWORD_INCORRECT);
117            AsyncResult.forMessage(result, null, ex);
118            result.sendToTarget();
119            return;
120        }
121
122        if (pin != null && pin.equals(mPinCode)) {
123            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: success!");
124            mPinUnlockAttempts = 0;
125            mSimLockedState = SimLockState.NONE;
126            mIccStatusChangedRegistrants.notifyRegistrants();
127
128            if (result != null) {
129                AsyncResult.forMessage(result, null, null);
130                result.sendToTarget();
131            }
132
133            return;
134        }
135
136        if (result != null) {
137            mPinUnlockAttempts ++;
138
139            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: failed! attempt=" +
140                    mPinUnlockAttempts);
141            if (mPinUnlockAttempts >= 3) {
142                Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: set state to REQUIRE_PUK");
143                mSimLockedState = SimLockState.REQUIRE_PUK;
144            }
145
146            CommandException ex = new CommandException(
147                    CommandException.Error.PASSWORD_INCORRECT);
148            AsyncResult.forMessage(result, null, ex);
149            result.sendToTarget();
150        }
151    }
152
153    public void supplyIccPuk(String puk, String newPin, Message result)  {
154        if (mSimLockedState != SimLockState.REQUIRE_PUK) {
155            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: wrong state, state=" +
156                    mSimLockedState);
157            CommandException ex = new CommandException(
158                    CommandException.Error.PASSWORD_INCORRECT);
159            AsyncResult.forMessage(result, null, ex);
160            result.sendToTarget();
161            return;
162        }
163
164        if (puk != null && puk.equals(SIM_PUK_CODE)) {
165            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: success!");
166            mSimLockedState = SimLockState.NONE;
167            mPukUnlockAttempts = 0;
168            mIccStatusChangedRegistrants.notifyRegistrants();
169
170            if (result != null) {
171                AsyncResult.forMessage(result, null, null);
172                result.sendToTarget();
173            }
174
175            return;
176        }
177
178        if (result != null) {
179            mPukUnlockAttempts ++;
180
181            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: failed! attempt=" +
182                    mPukUnlockAttempts);
183            if (mPukUnlockAttempts >= 10) {
184                Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: set state to SIM_PERM_LOCKED");
185                mSimLockedState = SimLockState.SIM_PERM_LOCKED;
186            }
187
188            CommandException ex = new CommandException(
189                    CommandException.Error.PASSWORD_INCORRECT);
190            AsyncResult.forMessage(result, null, ex);
191            result.sendToTarget();
192        }
193    }
194
195    public void supplyIccPin2(String pin2, Message result)  {
196        if (mSimFdnEnabledState != SimFdnState.REQUIRE_PIN2) {
197            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: wrong state, state=" +
198                    mSimFdnEnabledState);
199            CommandException ex = new CommandException(
200                    CommandException.Error.PASSWORD_INCORRECT);
201            AsyncResult.forMessage(result, null, ex);
202            result.sendToTarget();
203            return;
204        }
205
206        if (pin2 != null && pin2.equals(mPin2Code)) {
207            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: success!");
208            mPin2UnlockAttempts = 0;
209            mSimFdnEnabledState = SimFdnState.NONE;
210
211            if (result != null) {
212                AsyncResult.forMessage(result, null, null);
213                result.sendToTarget();
214            }
215
216            return;
217        }
218
219        if (result != null) {
220            mPin2UnlockAttempts ++;
221
222            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: failed! attempt=" +
223                    mPin2UnlockAttempts);
224            if (mPin2UnlockAttempts >= 3) {
225                Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: set state to REQUIRE_PUK2");
226                mSimFdnEnabledState = SimFdnState.REQUIRE_PUK2;
227            }
228
229            CommandException ex = new CommandException(
230                    CommandException.Error.PASSWORD_INCORRECT);
231            AsyncResult.forMessage(result, null, ex);
232            result.sendToTarget();
233        }
234    }
235
236    public void supplyIccPuk2(String puk2, String newPin2, Message result)  {
237        if (mSimFdnEnabledState != SimFdnState.REQUIRE_PUK2) {
238            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: wrong state, state=" +
239                    mSimLockedState);
240            CommandException ex = new CommandException(
241                    CommandException.Error.PASSWORD_INCORRECT);
242            AsyncResult.forMessage(result, null, ex);
243            result.sendToTarget();
244            return;
245        }
246
247        if (puk2 != null && puk2.equals(SIM_PUK2_CODE)) {
248            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: success!");
249            mSimFdnEnabledState = SimFdnState.NONE;
250            mPuk2UnlockAttempts = 0;
251
252            if (result != null) {
253                AsyncResult.forMessage(result, null, null);
254                result.sendToTarget();
255            }
256
257            return;
258        }
259
260        if (result != null) {
261            mPuk2UnlockAttempts ++;
262
263            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: failed! attempt=" +
264                    mPuk2UnlockAttempts);
265            if (mPuk2UnlockAttempts >= 10) {
266                Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: set state to SIM_PERM_LOCKED");
267                mSimFdnEnabledState = SimFdnState.SIM_PERM_LOCKED;
268            }
269
270            CommandException ex = new CommandException(
271                    CommandException.Error.PASSWORD_INCORRECT);
272            AsyncResult.forMessage(result, null, ex);
273            result.sendToTarget();
274        }
275    }
276
277    public void changeIccPin(String oldPin, String newPin, Message result)  {
278        if (oldPin != null && oldPin.equals(mPinCode)) {
279            mPinCode = newPin;
280            if (result != null) {
281                AsyncResult.forMessage(result, null, null);
282                result.sendToTarget();
283            }
284
285            return;
286        }
287
288        if (result != null) {
289            Rlog.i(LOG_TAG, "[SimCmd] changeIccPin: pin failed!");
290
291            CommandException ex = new CommandException(
292                    CommandException.Error.PASSWORD_INCORRECT);
293            AsyncResult.forMessage(result, null, ex);
294            result.sendToTarget();
295        }
296    }
297
298    public void changeIccPin2(String oldPin2, String newPin2, Message result)  {
299        if (oldPin2 != null && oldPin2.equals(mPin2Code)) {
300            mPin2Code = newPin2;
301            if (result != null) {
302                AsyncResult.forMessage(result, null, null);
303                result.sendToTarget();
304            }
305
306            return;
307        }
308
309        if (result != null) {
310            Rlog.i(LOG_TAG, "[SimCmd] changeIccPin2: pin2 failed!");
311
312            CommandException ex = new CommandException(
313                    CommandException.Error.PASSWORD_INCORRECT);
314            AsyncResult.forMessage(result, null, ex);
315            result.sendToTarget();
316        }
317    }
318
319    public void
320    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) {
321        unimplemented(result);
322    }
323
324    public void
325    setSuppServiceNotifications(boolean enable, Message result) {
326        resultSuccess(result, null);
327
328        if (enable && mSsnNotifyOn) {
329            Rlog.w(LOG_TAG, "Supp Service Notifications already enabled!");
330        }
331
332        mSsnNotifyOn = enable;
333    }
334
335    @Override
336    public void queryFacilityLock(String facility, String pin,
337                                   int serviceClass, Message result) {
338        queryFacilityLockForApp(facility, pin, serviceClass, null, result);
339    }
340
341    @Override
342    public void queryFacilityLockForApp(String facility, String pin, int serviceClass,
343            String appId, Message result) {
344        if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) {
345            if (result != null) {
346                int[] r = new int[1];
347                r[0] = (mSimLockEnabled ? 1 : 0);
348                Rlog.i(LOG_TAG, "[SimCmd] queryFacilityLock: SIM is "
349                        + (r[0] == 0 ? "unlocked" : "locked"));
350                AsyncResult.forMessage(result, r, null);
351                result.sendToTarget();
352            }
353            return;
354        } else if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) {
355            if (result != null) {
356                int[] r = new int[1];
357                r[0] = (mSimFdnEnabled ? 1 : 0);
358                Rlog.i(LOG_TAG, "[SimCmd] queryFacilityLock: FDN is "
359                        + (r[0] == 0 ? "disabled" : "enabled"));
360                AsyncResult.forMessage(result, r, null);
361                result.sendToTarget();
362            }
363            return;
364        }
365
366        unimplemented(result);
367    }
368
369    @Override
370    public void setFacilityLock(String facility, boolean lockEnabled, String pin, int serviceClass,
371            Message result) {
372        setFacilityLockForApp(facility, lockEnabled, pin, serviceClass, null, result);
373    }
374
375    @Override
376    public void setFacilityLockForApp(String facility, boolean lockEnabled,
377                                 String pin, int serviceClass, String appId,
378                                 Message result) {
379        if (facility != null &&
380                facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) {
381            if (pin != null && pin.equals(mPinCode)) {
382                Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin is valid");
383                mSimLockEnabled = lockEnabled;
384
385                if (result != null) {
386                    AsyncResult.forMessage(result, null, null);
387                    result.sendToTarget();
388                }
389
390                return;
391            }
392
393            if (result != null) {
394                Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin failed!");
395
396                CommandException ex = new CommandException(
397                        CommandException.Error.GENERIC_FAILURE);
398                AsyncResult.forMessage(result, null, ex);
399                result.sendToTarget();
400            }
401
402            return;
403        }  else if (facility != null &&
404                facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) {
405            if (pin != null && pin.equals(mPin2Code)) {
406                Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 is valid");
407                mSimFdnEnabled = lockEnabled;
408
409                if (result != null) {
410                    AsyncResult.forMessage(result, null, null);
411                    result.sendToTarget();
412                }
413
414                return;
415            }
416
417            if (result != null) {
418                Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 failed!");
419
420                CommandException ex = new CommandException(
421                        CommandException.Error.GENERIC_FAILURE);
422                AsyncResult.forMessage(result, null, ex);
423                result.sendToTarget();
424            }
425
426            return;
427        }
428
429        unimplemented(result);
430    }
431
432    public void supplyNetworkDepersonalization(String netpin, Message result)  {
433        unimplemented(result);
434    }
435
436    /**
437     *  returned message
438     *  retMsg.obj = AsyncResult ar
439     *  ar.exception carries exception on failure
440     *  ar.userObject contains the original value of result.obj
441     *  ar.result contains a List of DriverCall
442     *      The ar.result List is sorted by DriverCall.index
443     */
444    public void getCurrentCalls (Message result) {
445        if ((mState == RadioState.RADIO_ON) && !isSimLocked()) {
446            //Rlog.i("GSM", "[SimCmds] getCurrentCalls");
447            resultSuccess(result, simulatedCallState.getDriverCalls());
448        } else {
449            //Rlog.i("GSM", "[SimCmds] getCurrentCalls: RADIO_OFF or SIM not ready!");
450            resultFail(result,
451                new CommandException(
452                    CommandException.Error.RADIO_NOT_AVAILABLE));
453        }
454    }
455
456    /**
457     *  @deprecated
458     */
459    public void getPDPContextList(Message result) {
460        getDataCallList(result);
461    }
462
463    /**
464     *  returned message
465     *  retMsg.obj = AsyncResult ar
466     *  ar.exception carries exception on failure
467     *  ar.userObject contains the original value of result.obj
468     *  ar.result contains a List of DataCallState
469     */
470    public void getDataCallList(Message result) {
471        resultSuccess(result, new ArrayList<DataCallState>(0));
472    }
473
474    /**
475     *  returned message
476     *  retMsg.obj = AsyncResult ar
477     *  ar.exception carries exception on failure
478     *  ar.userObject contains the original value of result.obj
479     *  ar.result is null on success and failure
480     *
481     * CLIR_DEFAULT     == on "use subscription default value"
482     * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation)
483     * CLIR_INVOCATION  == on "CLIR invocation" (restrict CLI presentation)
484     */
485    public void dial (String address, int clirMode, Message result) {
486        simulatedCallState.onDial(address);
487
488        resultSuccess(result, null);
489    }
490
491    /**
492     *  returned message
493     *  retMsg.obj = AsyncResult ar
494     *  ar.exception carries exception on failure
495     *  ar.userObject contains the original value of result.obj
496     *  ar.result is null on success and failure
497     *
498     * CLIR_DEFAULT     == on "use subscription default value"
499     * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation)
500     * CLIR_INVOCATION  == on "CLIR invocation" (restrict CLI presentation)
501     */
502    public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
503        simulatedCallState.onDial(address);
504
505        resultSuccess(result, null);
506    }
507
508    public void getIMSI(Message result) {
509        getIMSIForApp(null, result);
510    }
511    /**
512     *  returned message
513     *  retMsg.obj = AsyncResult ar
514     *  ar.exception carries exception on failure
515     *  ar.userObject contains the original value of result.obj
516     *  ar.result is String containing IMSI on success
517     */
518    public void getIMSIForApp(String aid, Message result) {
519        resultSuccess(result, "012345678901234");
520    }
521
522    /**
523     *  returned message
524     *  retMsg.obj = AsyncResult ar
525     *  ar.exception carries exception on failure
526     *  ar.userObject contains the original value of result.obj
527     *  ar.result is String containing IMEI on success
528     */
529    public void getIMEI(Message result) {
530        resultSuccess(result, "012345678901234");
531    }
532
533    /**
534     *  returned message
535     *  retMsg.obj = AsyncResult ar
536     *  ar.exception carries exception on failure
537     *  ar.userObject contains the original value of result.obj
538     *  ar.result is String containing IMEISV on success
539     */
540    public void getIMEISV(Message result) {
541        resultSuccess(result, "99");
542    }
543
544    /**
545     * Hang up one individual connection.
546     *  returned message
547     *  retMsg.obj = AsyncResult ar
548     *  ar.exception carries exception on failure
549     *  ar.userObject contains the original value of result.obj
550     *  ar.result is null on success and failure
551     *
552     *  3GPP 22.030 6.5.5
553     *  "Releases a specific active call X"
554     */
555    public void hangupConnection (int gsmIndex, Message result) {
556        boolean success;
557
558        success = simulatedCallState.onChld('1', (char)('0'+gsmIndex));
559
560        if (!success){
561            Rlog.i("GSM", "[SimCmd] hangupConnection: resultFail");
562            resultFail(result, new RuntimeException("Hangup Error"));
563        } else {
564            Rlog.i("GSM", "[SimCmd] hangupConnection: resultSuccess");
565            resultSuccess(result, null);
566        }
567    }
568
569    /**
570     * 3GPP 22.030 6.5.5
571     *  "Releases all held calls or sets User Determined User Busy (UDUB)
572     *   for a waiting call."
573     *  ar.exception carries exception on failure
574     *  ar.userObject contains the original value of result.obj
575     *  ar.result is null on success and failure
576     */
577    public void hangupWaitingOrBackground (Message result) {
578        boolean success;
579
580        success = simulatedCallState.onChld('0', '\0');
581
582        if (!success){
583            resultFail(result, new RuntimeException("Hangup Error"));
584        } else {
585            resultSuccess(result, null);
586        }
587    }
588
589    /**
590     * 3GPP 22.030 6.5.5
591     * "Releases all active calls (if any exist) and accepts
592     *  the other (held or waiting) call."
593     *
594     *  ar.exception carries exception on failure
595     *  ar.userObject contains the original value of result.obj
596     *  ar.result is null on success and failure
597     */
598    public void hangupForegroundResumeBackground (Message result) {
599        boolean success;
600
601        success = simulatedCallState.onChld('1', '\0');
602
603        if (!success){
604            resultFail(result, new RuntimeException("Hangup Error"));
605        } else {
606            resultSuccess(result, null);
607        }
608    }
609
610    /**
611     * 3GPP 22.030 6.5.5
612     * "Places all active calls (if any exist) on hold and accepts
613     *  the other (held or waiting) call."
614     *
615     *  ar.exception carries exception on failure
616     *  ar.userObject contains the original value of result.obj
617     *  ar.result is null on success and failure
618     */
619    public void switchWaitingOrHoldingAndActive (Message result) {
620        boolean success;
621
622        success = simulatedCallState.onChld('2', '\0');
623
624        if (!success){
625            resultFail(result, new RuntimeException("Hangup Error"));
626        } else {
627            resultSuccess(result, null);
628        }
629    }
630
631    /**
632     * 3GPP 22.030 6.5.5
633     * "Adds a held call to the conversation"
634     *
635     *  ar.exception carries exception on failure
636     *  ar.userObject contains the original value of result.obj
637     *  ar.result is null on success and failure
638     */
639    public void conference (Message result) {
640        boolean success;
641
642        success = simulatedCallState.onChld('3', '\0');
643
644        if (!success){
645            resultFail(result, new RuntimeException("Hangup Error"));
646        } else {
647            resultSuccess(result, null);
648        }
649    }
650
651    /**
652     * 3GPP 22.030 6.5.5
653     * "Connects the two calls and disconnects the subscriber from both calls"
654     *
655     *  ar.exception carries exception on failure
656     *  ar.userObject contains the original value of result.obj
657     *  ar.result is null on success and failure
658     */
659    public void explicitCallTransfer (Message result) {
660        boolean success;
661
662        success = simulatedCallState.onChld('4', '\0');
663
664        if (!success){
665            resultFail(result, new RuntimeException("Hangup Error"));
666        } else {
667            resultSuccess(result, null);
668        }
669    }
670
671    /**
672     * 3GPP 22.030 6.5.5
673     * "Places all active calls on hold except call X with which
674     *  communication shall be supported."
675     */
676    public void separateConnection (int gsmIndex, Message result) {
677        boolean success;
678
679        char ch = (char)(gsmIndex + '0');
680        success = simulatedCallState.onChld('2', ch);
681
682        if (!success){
683            resultFail(result, new RuntimeException("Hangup Error"));
684        } else {
685            resultSuccess(result, null);
686        }
687    }
688
689    /**
690     *
691     *  ar.exception carries exception on failure
692     *  ar.userObject contains the original value of result.obj
693     *  ar.result is null on success and failure
694     */
695    public void acceptCall (Message result) {
696        boolean success;
697
698        success = simulatedCallState.onAnswer();
699
700        if (!success){
701            resultFail(result, new RuntimeException("Hangup Error"));
702        } else {
703            resultSuccess(result, null);
704        }
705    }
706
707    /**
708     *  also known as UDUB
709     *  ar.exception carries exception on failure
710     *  ar.userObject contains the original value of result.obj
711     *  ar.result is null on success and failure
712     */
713    public void rejectCall (Message result) {
714        boolean success;
715
716        success = simulatedCallState.onChld('0', '\0');
717
718        if (!success){
719            resultFail(result, new RuntimeException("Hangup Error"));
720        } else {
721            resultSuccess(result, null);
722        }
723    }
724
725    /**
726     * cause code returned as Integer in Message.obj.response
727     * Returns integer cause code defined in TS 24.008
728     * Annex H or closest approximation.
729     * Most significant codes:
730     * - Any defined in 22.001 F.4 (for generating busy/congestion)
731     * - Cause 68: ACM >= ACMMax
732     */
733    public void getLastCallFailCause (Message result) {
734        int[] ret = new int[1];
735
736        ret[0] = nextCallFailCause;
737        resultSuccess(result, ret);
738    }
739
740    /**
741     * @deprecated
742     */
743    public void getLastPdpFailCause (Message result) {
744        unimplemented(result);
745    }
746
747    public void getLastDataCallFailCause(Message result) {
748        //
749        unimplemented(result);
750    }
751
752    public void setMute (boolean enableMute, Message result) {unimplemented(result);}
753
754    public void getMute (Message result) {unimplemented(result);}
755
756    /**
757     * response.obj is an AsyncResult
758     * response.obj.result is an int[2]
759     * response.obj.result[0] is received signal strength (0-31, 99)
760     * response.obj.result[1] is  bit error rate (0-7, 99)
761     * as defined in TS 27.007 8.5
762     */
763    public void getSignalStrength (Message result) {
764        int ret[] = new int[2];
765
766        ret[0] = 23;
767        ret[1] = 0;
768
769        resultSuccess(result, ret);
770    }
771
772     /**
773     * Assign a specified band for RF configuration.
774     *
775     * @param bandMode one of BM_*_BAND
776     * @param result is callback message
777     */
778    public void setBandMode (int bandMode, Message result) {
779        resultSuccess(result, null);
780    }
781
782    /**
783     * Query the list of band mode supported by RF.
784     *
785     * @param result is callback message
786     *        ((AsyncResult)response.obj).result  is an int[] with every
787     *        element representing one available BM_*_BAND
788     */
789    public void queryAvailableBandMode (Message result) {
790        int ret[] = new int [4];
791
792        ret[0] = 4;
793        ret[1] = Phone.BM_US_BAND;
794        ret[2] = Phone.BM_JPN_BAND;
795        ret[3] = Phone.BM_AUS_BAND;
796
797        resultSuccess(result, ret);
798    }
799
800    /**
801     * {@inheritDoc}
802     */
803    public void sendTerminalResponse(String contents, Message response) {
804        resultSuccess(response, null);
805    }
806
807    /**
808     * {@inheritDoc}
809     */
810    public void sendEnvelope(String contents, Message response) {
811        resultSuccess(response, null);
812    }
813
814    /**
815     * {@inheritDoc}
816     */
817    public void sendEnvelopeWithStatus(String contents, Message response) {
818        resultSuccess(response, null);
819    }
820
821    /**
822     * {@inheritDoc}
823     */
824    public void handleCallSetupRequestFromSim(
825            boolean accept, Message response) {
826        resultSuccess(response, null);
827    }
828
829    /**
830     * response.obj.result is an String[14]
831     * See ril.h for details
832     *
833     * Please note that registration state 4 ("unknown") is treated
834     * as "out of service" above
835     */
836    public void getVoiceRegistrationState (Message result) {
837        String ret[] = new String[14];
838
839        ret[0] = "5"; // registered roam
840        ret[1] = null;
841        ret[2] = null;
842        ret[3] = null;
843        ret[4] = null;
844        ret[5] = null;
845        ret[6] = null;
846        ret[7] = null;
847        ret[8] = null;
848        ret[9] = null;
849        ret[10] = null;
850        ret[11] = null;
851        ret[12] = null;
852        ret[13] = null;
853
854        resultSuccess(result, ret);
855    }
856
857    /**
858     * response.obj.result is an String[4]
859     * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2
860     * response.obj.result[1] is LAC if registered or NULL if not
861     * response.obj.result[2] is CID if registered or NULL if not
862     * response.obj.result[3] indicates the available radio technology, where:
863     *      0 == unknown
864     *      1 == GPRS only
865     *      2 == EDGE
866     *      3 == UMTS
867     *
868     * valid LAC are 0x0000 - 0xffff
869     * valid CID are 0x00000000 - 0xffffffff
870     *
871     * Please note that registration state 4 ("unknown") is treated
872     * as "out of service" in the Android telephony system
873     */
874    public void getDataRegistrationState (Message result) {
875        String ret[] = new String[4];
876
877        ret[0] = "5"; // registered roam
878        ret[1] = null;
879        ret[2] = null;
880        ret[3] = "2";
881
882        resultSuccess(result, ret);
883    }
884
885    /**
886     * response.obj.result is a String[3]
887     * response.obj.result[0] is long alpha or null if unregistered
888     * response.obj.result[1] is short alpha or null if unregistered
889     * response.obj.result[2] is numeric or null if unregistered
890     */
891    public void getOperator(Message result) {
892        String[] ret = new String[3];
893
894        ret[0] = "El Telco Loco";
895        ret[1] = "Telco Loco";
896        ret[2] = "001001";
897
898        resultSuccess(result, ret);
899    }
900
901    /**
902     *  ar.exception carries exception on failure
903     *  ar.userObject contains the original value of result.obj
904     *  ar.result is null on success and failure
905     */
906    public void sendDtmf(char c, Message result) {
907        resultSuccess(result, null);
908    }
909
910    /**
911     *  ar.exception carries exception on failure
912     *  ar.userObject contains the original value of result.obj
913     *  ar.result is null on success and failure
914     */
915    public void startDtmf(char c, Message result) {
916        resultSuccess(result, null);
917    }
918
919    /**
920     *  ar.exception carries exception on failure
921     *  ar.userObject contains the original value of result.obj
922     *  ar.result is null on success and failure
923     */
924    public void stopDtmf(Message result) {
925        resultSuccess(result, null);
926    }
927
928    /**
929     *  ar.exception carries exception on failure
930     *  ar.userObject contains the original value of result.obj
931     *  ar.result is null on success and failure
932     */
933    public void sendBurstDtmf(String dtmfString, int on, int off, Message result) {
934        resultSuccess(result, null);
935    }
936
937    /**
938     * smscPDU is smsc address in PDU form GSM BCD format prefixed
939     *      by a length byte (as expected by TS 27.005) or NULL for default SMSC
940     * pdu is SMS in PDU format as an ASCII hex string
941     *      less the SMSC address
942     */
943    public void sendSMS (String smscPDU, String pdu, Message result) {unimplemented(result);}
944
945    public void deleteSmsOnSim(int index, Message response) {
946        Rlog.d(LOG_TAG, "Delete message at index " + index);
947        unimplemented(response);
948    }
949
950    public void deleteSmsOnRuim(int index, Message response) {
951        Rlog.d(LOG_TAG, "Delete RUIM message at index " + index);
952        unimplemented(response);
953    }
954
955    public void writeSmsToSim(int status, String smsc, String pdu, Message response) {
956        Rlog.d(LOG_TAG, "Write SMS to SIM with status " + status);
957        unimplemented(response);
958    }
959
960    public void writeSmsToRuim(int status, String pdu, Message response) {
961        Rlog.d(LOG_TAG, "Write SMS to RUIM with status " + status);
962        unimplemented(response);
963    }
964
965    public void setupDataCall(String radioTechnology, String profile,
966            String apn, String user, String password, String authType,
967            String protocol, Message result) {
968        unimplemented(result);
969    }
970
971    public void deactivateDataCall(int cid, int reason, Message result) {unimplemented(result);}
972
973    public void setPreferredNetworkType(int networkType , Message result) {
974        mNetworkType = networkType;
975        resultSuccess(result, null);
976    }
977
978    public void getPreferredNetworkType(Message result) {
979        int ret[] = new int[1];
980
981        ret[0] = mNetworkType;
982        resultSuccess(result, ret);
983    }
984
985    public void getNeighboringCids(Message result) {
986        int ret[] = new int[7];
987
988        ret[0] = 6;
989        for (int i = 1; i<7; i++) {
990            ret[i] = i;
991        }
992        resultSuccess(result, ret);
993    }
994
995    public void setLocationUpdates(boolean enable, Message response) {
996        unimplemented(response);
997    }
998
999    public void getSmscAddress(Message result) {
1000        unimplemented(result);
1001    }
1002
1003    public void setSmscAddress(String address, Message result) {
1004        unimplemented(result);
1005    }
1006
1007    public void reportSmsMemoryStatus(boolean available, Message result) {
1008        unimplemented(result);
1009    }
1010
1011    public void reportStkServiceIsRunning(Message result) {
1012        resultSuccess(result, null);
1013    }
1014
1015    @Override
1016    public void getCdmaSubscriptionSource(Message result) {
1017        unimplemented(result);
1018    }
1019
1020    private boolean isSimLocked() {
1021        if (mSimLockedState != SimLockState.NONE) {
1022            return true;
1023        }
1024        return false;
1025    }
1026
1027    public void setRadioPower(boolean on, Message result) {
1028        if(on) {
1029            setRadioState(RadioState.RADIO_ON);
1030        } else {
1031            setRadioState(RadioState.RADIO_OFF);
1032        }
1033    }
1034
1035
1036    public void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) {
1037        unimplemented(result);
1038    }
1039
1040    public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) {
1041        unimplemented(result);
1042    }
1043
1044    public void acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu,
1045            Message result) {
1046        unimplemented(result);
1047    }
1048
1049    public void iccIO(int command, int fileid, String path, int p1, int p2, int p3, String data,
1050            String pin2, Message response) {
1051        iccIOForApp(command, fileid, path, p1, p2, p3, data,pin2, null, response);
1052    }
1053
1054    /**
1055     * parameters equivalent to 27.007 AT+CRSM command
1056     * response.obj will be an AsyncResult
1057     * response.obj.userObj will be a SimIoResult on success
1058     */
1059    public void iccIOForApp (int command, int fileid, String path, int p1, int p2,
1060                       int p3, String data, String pin2, String aid, Message result) {
1061        unimplemented(result);
1062    }
1063
1064    /**
1065     * (AsyncResult)response.obj).result is an int[] with element [0] set to
1066     * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned".
1067     *
1068     * @param response is callback message
1069     */
1070    public void queryCLIP(Message response) { unimplemented(response); }
1071
1072
1073    /**
1074     * response.obj will be a an int[2]
1075     *
1076     * response.obj[0] will be TS 27.007 +CLIR parameter 'n'
1077     *  0 presentation indicator is used according to the subscription of the CLIR service
1078     *  1 CLIR invocation
1079     *  2 CLIR suppression
1080     *
1081     * response.obj[1] will be TS 27.007 +CLIR parameter 'm'
1082     *  0 CLIR not provisioned
1083     *  1 CLIR provisioned in permanent mode
1084     *  2 unknown (e.g. no network, etc.)
1085     *  3 CLIR temporary mode presentation restricted
1086     *  4 CLIR temporary mode presentation allowed
1087     */
1088
1089    public void getCLIR(Message result) {unimplemented(result);}
1090
1091    /**
1092     * clirMode is one of the CLIR_* constants above
1093     *
1094     * response.obj is null
1095     */
1096
1097    public void setCLIR(int clirMode, Message result) {unimplemented(result);}
1098
1099    /**
1100     * (AsyncResult)response.obj).result is an int[] with element [0] set to
1101     * 0 for disabled, 1 for enabled.
1102     *
1103     * @param serviceClass is a sum of SERVICE_CLASS_*
1104     * @param response is callback message
1105     */
1106
1107    public void queryCallWaiting(int serviceClass, Message response) {
1108        unimplemented(response);
1109    }
1110
1111    /**
1112     * @param enable is true to enable, false to disable
1113     * @param serviceClass is a sum of SERVICE_CLASS_*
1114     * @param response is callback message
1115     */
1116
1117    public void setCallWaiting(boolean enable, int serviceClass,
1118            Message response) {
1119        unimplemented(response);
1120    }
1121
1122    /**
1123     * @param action is one of CF_ACTION_*
1124     * @param cfReason is one of CF_REASON_*
1125     * @param serviceClass is a sum of SERVICE_CLASSS_*
1126     */
1127    public void setCallForward(int action, int cfReason, int serviceClass,
1128            String number, int timeSeconds, Message result) {unimplemented(result);}
1129
1130    /**
1131     * cfReason is one of CF_REASON_*
1132     *
1133     * ((AsyncResult)response.obj).result will be an array of
1134     * CallForwardInfo's
1135     *
1136     * An array of length 0 means "disabled for all codes"
1137     */
1138    public void queryCallForwardStatus(int cfReason, int serviceClass,
1139            String number, Message result) {unimplemented(result);}
1140
1141    public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);}
1142    public void exitEmergencyCallbackMode(Message result) {unimplemented(result);}
1143    public void setNetworkSelectionModeManual(
1144            String operatorNumeric, Message result) {unimplemented(result);}
1145
1146    /**
1147     * Queries whether the current network selection mode is automatic
1148     * or manual
1149     *
1150     * ((AsyncResult)response.obj).result  is an int[] with element [0] being
1151     * a 0 for automatic selection and a 1 for manual selection
1152     */
1153
1154    public void getNetworkSelectionMode(Message result) {
1155        int ret[] = new int[1];
1156
1157        ret[0] = 0;
1158        resultSuccess(result, ret);
1159    }
1160
1161    /**
1162     * Queries the currently available networks
1163     *
1164     * ((AsyncResult)response.obj).result  is a List of NetworkInfo objects
1165     */
1166    public void getAvailableNetworks(Message result) {unimplemented(result);}
1167
1168    public void getBasebandVersion (Message result) {
1169        resultSuccess(result, "SimulatedCommands");
1170    }
1171
1172    /**
1173     * Simulates an incoming USSD message
1174     * @param statusCode  Status code string. See <code>setOnUSSD</code>
1175     * in CommandsInterface.java
1176     * @param message Message text to send or null if none
1177     */
1178    public void triggerIncomingUssd(String statusCode, String message) {
1179        if (mUSSDRegistrant != null) {
1180            String[] result = {statusCode, message};
1181            mUSSDRegistrant.notifyResult(result);
1182        }
1183    }
1184
1185
1186    public void sendUSSD (String ussdString, Message result) {
1187
1188        // We simulate this particular sequence
1189        if (ussdString.equals("#646#")) {
1190            resultSuccess(result, null);
1191
1192            // 0 == USSD-Notify
1193            triggerIncomingUssd("0", "You have NNN minutes remaining.");
1194        } else {
1195            resultSuccess(result, null);
1196
1197            triggerIncomingUssd("0", "All Done");
1198        }
1199    }
1200
1201    // inherited javadoc suffices
1202    public void cancelPendingUssd (Message response) {
1203        resultSuccess(response, null);
1204    }
1205
1206
1207    public void resetRadio(Message result) {
1208        unimplemented(result);
1209    }
1210
1211    public void invokeOemRilRequestRaw(byte[] data, Message response) {
1212        // Just echo back data
1213        if (response != null) {
1214            AsyncResult.forMessage(response).result = data;
1215            response.sendToTarget();
1216        }
1217    }
1218
1219    public void invokeOemRilRequestStrings(String[] strings, Message response) {
1220        // Just echo back data
1221        if (response != null) {
1222            AsyncResult.forMessage(response).result = strings;
1223            response.sendToTarget();
1224        }
1225    }
1226
1227    //***** SimulatedRadioControl
1228
1229
1230    /** Start the simulated phone ringing */
1231    public void
1232    triggerRing(String number) {
1233        simulatedCallState.triggerRing(number);
1234        mCallStateRegistrants.notifyRegistrants();
1235    }
1236
1237    public void
1238    progressConnectingCallState() {
1239        simulatedCallState.progressConnectingCallState();
1240        mCallStateRegistrants.notifyRegistrants();
1241    }
1242
1243    /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */
1244    public void
1245    progressConnectingToActive() {
1246        simulatedCallState.progressConnectingToActive();
1247        mCallStateRegistrants.notifyRegistrants();
1248    }
1249
1250    /** automatically progress mobile originated calls to ACTIVE.
1251     *  default to true
1252     */
1253    public void
1254    setAutoProgressConnectingCall(boolean b) {
1255        simulatedCallState.setAutoProgressConnectingCall(b);
1256    }
1257
1258    public void
1259    setNextDialFailImmediately(boolean b) {
1260        simulatedCallState.setNextDialFailImmediately(b);
1261    }
1262
1263    public void
1264    setNextCallFailCause(int gsmCause) {
1265        nextCallFailCause = gsmCause;
1266    }
1267
1268    public void
1269    triggerHangupForeground() {
1270        simulatedCallState.triggerHangupForeground();
1271        mCallStateRegistrants.notifyRegistrants();
1272    }
1273
1274    /** hangup holding calls */
1275    public void
1276    triggerHangupBackground() {
1277        simulatedCallState.triggerHangupBackground();
1278        mCallStateRegistrants.notifyRegistrants();
1279    }
1280
1281    public void triggerSsn(int type, int code) {
1282        SuppServiceNotification not = new SuppServiceNotification();
1283        not.notificationType = type;
1284        not.code = code;
1285        mSsnRegistrant.notifyRegistrant(new AsyncResult(null, not, null));
1286    }
1287
1288    public void
1289    shutdown() {
1290        setRadioState(RadioState.RADIO_UNAVAILABLE);
1291        Looper looper = mHandlerThread.getLooper();
1292        if (looper != null) {
1293            looper.quit();
1294        }
1295    }
1296
1297    /** hangup all */
1298
1299    public void
1300    triggerHangupAll() {
1301        simulatedCallState.triggerHangupAll();
1302        mCallStateRegistrants.notifyRegistrants();
1303    }
1304
1305    public void
1306    triggerIncomingSMS(String message) {
1307        //TODO
1308    }
1309
1310    public void
1311    pauseResponses() {
1312        pausedResponseCount++;
1313    }
1314
1315    public void
1316    resumeResponses() {
1317        pausedResponseCount--;
1318
1319        if (pausedResponseCount == 0) {
1320            for (int i = 0, s = pausedResponses.size(); i < s ; i++) {
1321                pausedResponses.get(i).sendToTarget();
1322            }
1323            pausedResponses.clear();
1324        } else {
1325            Rlog.e("GSM", "SimulatedCommands.resumeResponses < 0");
1326        }
1327    }
1328
1329    //***** Private Methods
1330
1331    private void unimplemented(Message result) {
1332        if (result != null) {
1333            AsyncResult.forMessage(result).exception
1334                = new RuntimeException("Unimplemented");
1335
1336            if (pausedResponseCount > 0) {
1337                pausedResponses.add(result);
1338            } else {
1339                result.sendToTarget();
1340            }
1341        }
1342    }
1343
1344    private void resultSuccess(Message result, Object ret) {
1345        if (result != null) {
1346            AsyncResult.forMessage(result).result = ret;
1347            if (pausedResponseCount > 0) {
1348                pausedResponses.add(result);
1349            } else {
1350                result.sendToTarget();
1351            }
1352        }
1353    }
1354
1355    private void resultFail(Message result, Throwable tr) {
1356        if (result != null) {
1357            AsyncResult.forMessage(result).exception = tr;
1358            if (pausedResponseCount > 0) {
1359                pausedResponses.add(result);
1360            } else {
1361                result.sendToTarget();
1362            }
1363        }
1364    }
1365
1366    // ***** Methods for CDMA support
1367    public void
1368    getDeviceIdentity(Message response) {
1369        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1370        unimplemented(response);
1371    }
1372
1373    public void
1374    getCDMASubscription(Message response) {
1375        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1376        unimplemented(response);
1377    }
1378
1379    public void
1380    setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response) {
1381        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1382        unimplemented(response);
1383    }
1384
1385    public void queryCdmaRoamingPreference(Message response) {
1386        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1387        unimplemented(response);
1388    }
1389
1390    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
1391        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1392        unimplemented(response);
1393    }
1394
1395    public void
1396    setPhoneType(int phoneType) {
1397        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1398    }
1399
1400    public void getPreferredVoicePrivacy(Message result) {
1401        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1402        unimplemented(result);
1403    }
1404
1405    public void setPreferredVoicePrivacy(boolean enable, Message result) {
1406        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1407        unimplemented(result);
1408    }
1409
1410    /**
1411     *  Set the TTY mode
1412     *
1413     * @param ttyMode is one of the following:
1414     * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF}
1415     * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL}
1416     * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO}
1417     * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
1418     * @param response is callback message
1419     */
1420    public void setTTYMode(int ttyMode, Message response) {
1421        Rlog.w(LOG_TAG, "Not implemented in SimulatedCommands");
1422        unimplemented(response);
1423    }
1424
1425    /**
1426     *  Query the TTY mode
1427     * (AsyncResult)response.obj).result is an int[] with element [0] set to
1428     * tty mode:
1429     * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF}
1430     * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL}
1431     * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO}
1432     * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
1433     * @param response is callback message
1434     */
1435    public void queryTTYMode(Message response) {
1436        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1437        unimplemented(response);
1438    }
1439
1440    /**
1441     * {@inheritDoc}
1442     */
1443    public void sendCDMAFeatureCode(String FeatureCode, Message response) {
1444        Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1445        unimplemented(response);
1446    }
1447
1448    /**
1449     * {@inheritDoc}
1450     */
1451    public void sendCdmaSms(byte[] pdu, Message response){
1452       Rlog.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
1453    }
1454
1455    public void setCdmaBroadcastActivation(boolean activate, Message response) {
1456        unimplemented(response);
1457
1458    }
1459
1460    public void getCdmaBroadcastConfig(Message response) {
1461        unimplemented(response);
1462
1463    }
1464
1465    public void setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs, Message response) {
1466        unimplemented(response);
1467    }
1468
1469    public void forceDataDormancy(Message response) {
1470        unimplemented(response);
1471    }
1472
1473
1474    public void setGsmBroadcastActivation(boolean activate, Message response) {
1475        unimplemented(response);
1476    }
1477
1478
1479    public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) {
1480        unimplemented(response);
1481    }
1482
1483    public void getGsmBroadcastConfig(Message response) {
1484        unimplemented(response);
1485    }
1486
1487    @Override
1488    public void supplyIccPinForApp(String pin, String aid, Message response) {
1489        unimplemented(response);
1490    }
1491
1492    @Override
1493    public void supplyIccPukForApp(String puk, String newPin, String aid, Message response) {
1494        unimplemented(response);
1495    }
1496
1497    @Override
1498    public void supplyIccPin2ForApp(String pin2, String aid, Message response) {
1499        unimplemented(response);
1500    }
1501
1502    @Override
1503    public void supplyIccPuk2ForApp(String puk2, String newPin2, String aid, Message response) {
1504        unimplemented(response);
1505    }
1506
1507    @Override
1508    public void changeIccPinForApp(String oldPin, String newPin, String aidPtr, Message response) {
1509        unimplemented(response);
1510    }
1511
1512    @Override
1513    public void changeIccPin2ForApp(String oldPin2, String newPin2, String aidPtr,
1514            Message response) {
1515        unimplemented(response);
1516    }
1517
1518    public void requestIsimAuthentication(String nonce, Message response) {
1519        unimplemented(response);
1520    }
1521
1522    public void getVoiceRadioTechnology(Message response) {
1523        unimplemented(response);
1524    }
1525}
1526