[go: nahoru, domu]

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.Handler;
21import android.os.HandlerThread;
22import android.os.Looper;
23import android.os.Message;
24import android.os.Parcel;
25import android.os.Registrant;
26import android.os.SystemClock;
27import android.service.carrier.CarrierIdentifier;
28import android.telephony.CellInfo;
29import android.telephony.CellInfoGsm;
30import android.telephony.Rlog;
31import android.telephony.ServiceState;
32import android.telephony.SignalStrength;
33import android.telephony.IccOpenLogicalChannelResponse;
34
35import com.android.internal.annotations.VisibleForTesting;
36import com.android.internal.telephony.BaseCommands;
37import com.android.internal.telephony.CommandException;
38import com.android.internal.telephony.CommandsInterface;
39import com.android.internal.telephony.PhoneConstants;
40import com.android.internal.telephony.SmsResponse;
41import com.android.internal.telephony.RadioCapability;
42import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
43import com.android.internal.telephony.dataconnection.DataCallResponse;
44import com.android.internal.telephony.dataconnection.DataProfile;
45import com.android.internal.telephony.Phone;
46import com.android.internal.telephony.UUSInfo;
47import com.android.internal.telephony.CallFailCause;
48import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
49import com.android.internal.telephony.gsm.SuppServiceNotification;
50import com.android.internal.telephony.LastCallFailCause;
51import com.android.internal.telephony.uicc.IccCardStatus;
52import com.android.internal.telephony.uicc.IccIoResult;
53
54import java.util.ArrayList;
55import java.util.concurrent.atomic.AtomicBoolean;
56import java.util.List;
57import java.util.concurrent.atomic.AtomicInteger;
58
59public class SimulatedCommands extends BaseCommands
60        implements CommandsInterface, SimulatedRadioControl {
61    private final static String LOG_TAG = "SimulatedCommands";
62
63    private enum SimLockState {
64        NONE,
65        REQUIRE_PIN,
66        REQUIRE_PUK,
67        SIM_PERM_LOCKED
68    }
69
70    private enum SimFdnState {
71        NONE,
72        REQUIRE_PIN2,
73        REQUIRE_PUK2,
74        SIM_PERM_LOCKED
75    }
76
77    private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE;
78    public final static String DEFAULT_SIM_PIN_CODE = "1234";
79    private final static String SIM_PUK_CODE = "12345678";
80    private final static SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE;
81    public final static String DEFAULT_SIM_PIN2_CODE = "5678";
82    private final static String SIM_PUK2_CODE = "87654321";
83    public final static String FAKE_LONG_NAME = "Fake long name";
84    public final static String FAKE_SHORT_NAME = "Fake short name";
85    public final static String FAKE_MCC_MNC = "310260";
86    public final static String FAKE_IMEI = "012345678901234";
87    public final static String FAKE_IMEISV = "99";
88    public final static String FAKE_ESN = "1234";
89    public final static String FAKE_MEID = "1234";
90    public final static int DEFAULT_PIN1_ATTEMPT = 5;
91    public final static int DEFAULT_PIN2_ATTEMPT = 5;
92
93    private String mImei;
94    private String mImeiSv;
95
96    //***** Instance Variables
97
98    SimulatedGsmCallState simulatedCallState;
99    HandlerThread mHandlerThread;
100    SimLockState mSimLockedState;
101    boolean mSimLockEnabled;
102    int mPinUnlockAttempts;
103    int mPukUnlockAttempts;
104    String mPinCode;
105    int mPin1attemptsRemaining = DEFAULT_PIN1_ATTEMPT;
106    SimFdnState mSimFdnEnabledState;
107    boolean mSimFdnEnabled;
108    int mPin2UnlockAttempts;
109    int mPuk2UnlockAttempts;
110    int mNetworkType;
111    String mPin2Code;
112    boolean mSsnNotifyOn = false;
113    private int mVoiceRegState = ServiceState.RIL_REG_STATE_HOME;
114    private int mVoiceRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_UMTS;
115    private int mDataRegState = ServiceState.RIL_REG_STATE_HOME;
116    private int mDataRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_UMTS;
117    private SignalStrength mSignalStrength;
118    private List<CellInfo> mCellInfoList;
119    private int[] mImsRegState;
120    private IccCardStatus mIccCardStatus;
121    private IccIoResult mIccIoResultForApduLogicalChannel;
122    private int mChannelId = IccOpenLogicalChannelResponse.INVALID_CHANNEL;
123
124    int mPausedResponseCount;
125    ArrayList<Message> mPausedResponses = new ArrayList<Message>();
126
127    int mNextCallFailCause = CallFailCause.NORMAL_CLEARING;
128
129    private boolean mDcSuccess = true;
130    private DataCallResponse mDcResponse;
131
132    //***** Constructor
133    public
134    SimulatedCommands() {
135        super(null);  // Don't log statistics
136        mHandlerThread = new HandlerThread("SimulatedCommands");
137        mHandlerThread.start();
138        Looper looper = mHandlerThread.getLooper();
139
140        simulatedCallState = new SimulatedGsmCallState(looper);
141
142        setRadioState(RadioState.RADIO_ON);
143        mSimLockedState = INITIAL_LOCK_STATE;
144        mSimLockEnabled = (mSimLockedState != SimLockState.NONE);
145        mPinCode = DEFAULT_SIM_PIN_CODE;
146        mSimFdnEnabledState = INITIAL_FDN_STATE;
147        mSimFdnEnabled = (mSimFdnEnabledState != SimFdnState.NONE);
148        mPin2Code = DEFAULT_SIM_PIN2_CODE;
149    }
150
151    private void log(String str) {
152        Rlog.d(LOG_TAG, str);
153    }
154
155    //***** CommandsInterface implementation
156
157    @Override
158    public void getIccCardStatus(Message result) {
159        if(mIccCardStatus!=null) {
160            resultSuccess(result, mIccCardStatus);
161        } else {
162            resultFail(result, null, new RuntimeException("IccCardStatus not set"));
163        }
164    }
165
166    @Override
167    public void supplyIccPin(String pin, Message result)  {
168        if (mSimLockedState != SimLockState.REQUIRE_PIN) {
169            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: wrong state, state=" +
170                    mSimLockedState);
171            CommandException ex = new CommandException(
172                    CommandException.Error.PASSWORD_INCORRECT);
173            resultFail(result, null, ex);
174            return;
175        }
176
177        if (pin != null && pin.equals(mPinCode)) {
178            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: success!");
179            mPinUnlockAttempts = 0;
180            mSimLockedState = SimLockState.NONE;
181            mIccStatusChangedRegistrants.notifyRegistrants();
182
183            resultSuccess(result, null);
184
185            return;
186        }
187
188        if (result != null) {
189            mPinUnlockAttempts ++;
190
191            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: failed! attempt=" +
192                    mPinUnlockAttempts);
193            if (mPinUnlockAttempts >= DEFAULT_PIN1_ATTEMPT) {
194                Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: set state to REQUIRE_PUK");
195                mSimLockedState = SimLockState.REQUIRE_PUK;
196            }
197
198            CommandException ex = new CommandException(
199                    CommandException.Error.PASSWORD_INCORRECT);
200            resultFail(result, null, ex);
201        }
202    }
203
204    @Override
205    public void supplyIccPuk(String puk, String newPin, Message result)  {
206        if (mSimLockedState != SimLockState.REQUIRE_PUK) {
207            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: wrong state, state=" +
208                    mSimLockedState);
209            CommandException ex = new CommandException(
210                    CommandException.Error.PASSWORD_INCORRECT);
211            resultFail(result, null, ex);
212            return;
213        }
214
215        if (puk != null && puk.equals(SIM_PUK_CODE)) {
216            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: success!");
217            mSimLockedState = SimLockState.NONE;
218            mPukUnlockAttempts = 0;
219            mIccStatusChangedRegistrants.notifyRegistrants();
220
221            resultSuccess(result, null);
222            return;
223        }
224
225        if (result != null) {
226            mPukUnlockAttempts ++;
227
228            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: failed! attempt=" +
229                    mPukUnlockAttempts);
230            if (mPukUnlockAttempts >= 10) {
231                Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: set state to SIM_PERM_LOCKED");
232                mSimLockedState = SimLockState.SIM_PERM_LOCKED;
233            }
234
235            CommandException ex = new CommandException(
236                    CommandException.Error.PASSWORD_INCORRECT);
237            resultFail(result, null, ex);
238        }
239    }
240
241    @Override
242    public void supplyIccPin2(String pin2, Message result)  {
243        if (mSimFdnEnabledState != SimFdnState.REQUIRE_PIN2) {
244            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: wrong state, state=" +
245                    mSimFdnEnabledState);
246            CommandException ex = new CommandException(
247                    CommandException.Error.PASSWORD_INCORRECT);
248            resultFail(result, null, ex);
249            return;
250        }
251
252        if (pin2 != null && pin2.equals(mPin2Code)) {
253            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: success!");
254            mPin2UnlockAttempts = 0;
255            mSimFdnEnabledState = SimFdnState.NONE;
256
257            resultSuccess(result, null);
258            return;
259        }
260
261        if (result != null) {
262            mPin2UnlockAttempts ++;
263
264            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: failed! attempt=" +
265                    mPin2UnlockAttempts);
266            if (mPin2UnlockAttempts >= DEFAULT_PIN2_ATTEMPT) {
267                Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: set state to REQUIRE_PUK2");
268                mSimFdnEnabledState = SimFdnState.REQUIRE_PUK2;
269            }
270
271            CommandException ex = new CommandException(
272                    CommandException.Error.PASSWORD_INCORRECT);
273            resultFail(result, null, ex);
274        }
275    }
276
277    @Override
278    public void supplyIccPuk2(String puk2, String newPin2, Message result)  {
279        if (mSimFdnEnabledState != SimFdnState.REQUIRE_PUK2) {
280            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: wrong state, state=" +
281                    mSimLockedState);
282            CommandException ex = new CommandException(
283                    CommandException.Error.PASSWORD_INCORRECT);
284            resultFail(result, null, ex);
285            return;
286        }
287
288        if (puk2 != null && puk2.equals(SIM_PUK2_CODE)) {
289            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: success!");
290            mSimFdnEnabledState = SimFdnState.NONE;
291            mPuk2UnlockAttempts = 0;
292
293            resultSuccess(result, null);
294            return;
295        }
296
297        if (result != null) {
298            mPuk2UnlockAttempts ++;
299
300            Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: failed! attempt=" +
301                    mPuk2UnlockAttempts);
302            if (mPuk2UnlockAttempts >= 10) {
303                Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: set state to SIM_PERM_LOCKED");
304                mSimFdnEnabledState = SimFdnState.SIM_PERM_LOCKED;
305            }
306
307            CommandException ex = new CommandException(
308                    CommandException.Error.PASSWORD_INCORRECT);
309            resultFail(result, null, ex);
310        }
311    }
312
313    @Override
314    public void changeIccPin(String oldPin, String newPin, Message result)  {
315        if (oldPin != null && oldPin.equals(mPinCode)) {
316            mPinCode = newPin;
317            resultSuccess(result, null);
318
319            return;
320        }
321
322        Rlog.i(LOG_TAG, "[SimCmd] changeIccPin: pin failed!");
323
324        CommandException ex = new CommandException(
325                CommandException.Error.PASSWORD_INCORRECT);
326        resultFail(result, null, ex);
327    }
328
329    @Override
330    public void changeIccPin2(String oldPin2, String newPin2, Message result) {
331        if (oldPin2 != null && oldPin2.equals(mPin2Code)) {
332            mPin2Code = newPin2;
333            resultSuccess(result, null);
334
335            return;
336        }
337
338        Rlog.i(LOG_TAG, "[SimCmd] changeIccPin2: pin2 failed!");
339
340        CommandException ex = new CommandException(
341                CommandException.Error.PASSWORD_INCORRECT);
342        resultFail(result, null, ex);
343    }
344
345    @Override
346    public void
347    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) {
348        unimplemented(result);
349    }
350
351    @Override
352    public void
353    setSuppServiceNotifications(boolean enable, Message result) {
354        resultSuccess(result, null);
355
356        if (enable && mSsnNotifyOn) {
357            Rlog.w(LOG_TAG, "Supp Service Notifications already enabled!");
358        }
359
360        mSsnNotifyOn = enable;
361    }
362
363    @Override
364    public void queryFacilityLock(String facility, String pin,
365                                   int serviceClass, Message result) {
366        queryFacilityLockForApp(facility, pin, serviceClass, null, result);
367    }
368
369    @Override
370    public void queryFacilityLockForApp(String facility, String pin, int serviceClass,
371            String appId, Message result) {
372        if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) {
373            if (result != null) {
374                int[] r = new int[1];
375                r[0] = (mSimLockEnabled ? 1 : 0);
376                Rlog.i(LOG_TAG, "[SimCmd] queryFacilityLock: SIM is "
377                        + (r[0] == 0 ? "unlocked" : "locked"));
378                resultSuccess(result, r);
379            }
380            return;
381        } else if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) {
382            if (result != null) {
383                int[] r = new int[1];
384                r[0] = (mSimFdnEnabled ? 1 : 0);
385                Rlog.i(LOG_TAG, "[SimCmd] queryFacilityLock: FDN is "
386                        + (r[0] == 0 ? "disabled" : "enabled"));
387                resultSuccess(result, r);
388            }
389            return;
390        }
391
392        unimplemented(result);
393    }
394
395    @Override
396    public void setFacilityLock(String facility, boolean lockEnabled, String pin, int serviceClass,
397            Message result) {
398        setFacilityLockForApp(facility, lockEnabled, pin, serviceClass, null, result);
399    }
400
401    @Override
402    public void setFacilityLockForApp(String facility, boolean lockEnabled,
403                                 String pin, int serviceClass, String appId,
404                                 Message result) {
405        if (facility != null &&
406                facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) {
407            if (pin != null && pin.equals(mPinCode)) {
408                Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin is valid");
409                mSimLockEnabled = lockEnabled;
410
411                resultSuccess(result, null);
412
413                return;
414            }
415
416            Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin failed!");
417
418            CommandException ex = new CommandException(
419                    CommandException.Error.GENERIC_FAILURE);
420            resultFail(result, null, ex);
421
422            return;
423        }  else if (facility != null &&
424                facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) {
425            if (pin != null && pin.equals(mPin2Code)) {
426                Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 is valid");
427                mSimFdnEnabled = lockEnabled;
428
429                resultSuccess(result, null);
430
431                return;
432            }
433
434            Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 failed!");
435
436            CommandException ex = new CommandException(
437                    CommandException.Error.GENERIC_FAILURE);
438            resultFail(result, null, ex);
439
440            return;
441        }
442
443        unimplemented(result);
444    }
445
446    @Override
447    public void supplyNetworkDepersonalization(String netpin, Message result) {
448        unimplemented(result);
449    }
450
451    /**
452     *  returned message
453     *  retMsg.obj = AsyncResult ar
454     *  ar.exception carries exception on failure
455     *  ar.userObject contains the original value of result.obj
456     *  ar.result contains a List of DriverCall
457     *      The ar.result List is sorted by DriverCall.index
458     */
459    @Override
460    public void getCurrentCalls (Message result) {
461        SimulatedCommandsVerifier.getInstance().getCurrentCalls(result);
462        if ((mState == RadioState.RADIO_ON) && !isSimLocked()) {
463            //Rlog.i("GSM", "[SimCmds] getCurrentCalls");
464            resultSuccess(result, simulatedCallState.getDriverCalls());
465        } else {
466            //Rlog.i("GSM", "[SimCmds] getCurrentCalls: RADIO_OFF or SIM not ready!");
467            resultFail(result, null,
468                new CommandException(CommandException.Error.RADIO_NOT_AVAILABLE));
469        }
470    }
471
472    /**
473     *  @deprecated
474     */
475    @Deprecated
476    @Override
477    public void getPDPContextList(Message result) {
478        getDataCallList(result);
479    }
480
481    /**
482     *  returned message
483     *  retMsg.obj = AsyncResult ar
484     *  ar.exception carries exception on failure
485     *  ar.userObject contains the original value of result.obj
486     *  ar.result contains a List of DataCallResponse
487     */
488    @Override
489    public void getDataCallList(Message result) {
490        resultSuccess(result, new ArrayList<DataCallResponse>(0));
491    }
492
493    /**
494     *  returned message
495     *  retMsg.obj = AsyncResult ar
496     *  ar.exception carries exception on failure
497     *  ar.userObject contains the original value of result.obj
498     *  ar.result is null on success and failure
499     *
500     * CLIR_DEFAULT     == on "use subscription default value"
501     * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation)
502     * CLIR_INVOCATION  == on "CLIR invocation" (restrict CLI presentation)
503     */
504    @Override
505    public void dial (String address, int clirMode, Message result) {
506        SimulatedCommandsVerifier.getInstance().dial(address, clirMode, result);
507        simulatedCallState.onDial(address);
508
509        resultSuccess(result, null);
510    }
511
512    /**
513     *  returned message
514     *  retMsg.obj = AsyncResult ar
515     *  ar.exception carries exception on failure
516     *  ar.userObject contains the original value of result.obj
517     *  ar.result is null on success and failure
518     *
519     * CLIR_DEFAULT     == on "use subscription default value"
520     * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation)
521     * CLIR_INVOCATION  == on "CLIR invocation" (restrict CLI presentation)
522     */
523    @Override
524    public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
525        SimulatedCommandsVerifier.getInstance().dial(address, clirMode, uusInfo, result);
526        simulatedCallState.onDial(address);
527
528        resultSuccess(result, null);
529    }
530
531    @Override
532    public void getIMSI(Message result) {
533        getIMSIForApp(null, result);
534    }
535    /**
536     *  returned message
537     *  retMsg.obj = AsyncResult ar
538     *  ar.exception carries exception on failure
539     *  ar.userObject contains the original value of result.obj
540     *  ar.result is String containing IMSI on success
541     */
542    @Override
543    public void getIMSIForApp(String aid, Message result) {
544        resultSuccess(result, "012345678901234");
545    }
546
547    public void setIMEI(String imei) {
548        mImei = imei;
549    }
550
551    /**
552     *  returned message
553     *  retMsg.obj = AsyncResult ar
554     *  ar.exception carries exception on failure
555     *  ar.userObject contains the original value of result.obj
556     *  ar.result is String containing IMEI on success
557     */
558    @Override
559    public void getIMEI(Message result) {
560        SimulatedCommandsVerifier.getInstance().getIMEI(result);
561        resultSuccess(result, mImei != null ? mImei : FAKE_IMEI);
562    }
563
564    public void setIMEISV(String imeisv) {
565        mImeiSv = imeisv;
566    }
567
568    /**
569     *  returned message
570     *  retMsg.obj = AsyncResult ar
571     *  ar.exception carries exception on failure
572     *  ar.userObject contains the original value of result.obj
573     *  ar.result is String containing IMEISV on success
574     */
575    @Override
576    public void getIMEISV(Message result) {
577        SimulatedCommandsVerifier.getInstance().getIMEISV(result);
578        resultSuccess(result, mImeiSv != null ? mImeiSv : FAKE_IMEISV);
579    }
580
581    /**
582     * Hang up one individual connection.
583     *  returned message
584     *  retMsg.obj = AsyncResult ar
585     *  ar.exception carries exception on failure
586     *  ar.userObject contains the original value of result.obj
587     *  ar.result is null on success and failure
588     *
589     *  3GPP 22.030 6.5.5
590     *  "Releases a specific active call X"
591     */
592    @Override
593    public void hangupConnection (int gsmIndex, Message result) {
594        boolean success;
595
596        success = simulatedCallState.onChld('1', (char)('0'+gsmIndex));
597
598        if (!success){
599            Rlog.i("GSM", "[SimCmd] hangupConnection: resultFail");
600            resultFail(result, null, new RuntimeException("Hangup Error"));
601        } else {
602            Rlog.i("GSM", "[SimCmd] hangupConnection: resultSuccess");
603            resultSuccess(result, null);
604        }
605    }
606
607    /**
608     * 3GPP 22.030 6.5.5
609     *  "Releases all held calls or sets User Determined User Busy (UDUB)
610     *   for a waiting call."
611     *  ar.exception carries exception on failure
612     *  ar.userObject contains the original value of result.obj
613     *  ar.result is null on success and failure
614     */
615    @Override
616    public void hangupWaitingOrBackground (Message result) {
617        boolean success;
618
619        success = simulatedCallState.onChld('0', '\0');
620
621        if (!success){
622            resultFail(result, null, new RuntimeException("Hangup Error"));
623        } else {
624            resultSuccess(result, null);
625        }
626    }
627
628    /**
629     * 3GPP 22.030 6.5.5
630     * "Releases all active calls (if any exist) and accepts
631     *  the other (held or waiting) call."
632     *
633     *  ar.exception carries exception on failure
634     *  ar.userObject contains the original value of result.obj
635     *  ar.result is null on success and failure
636     */
637    @Override
638    public void hangupForegroundResumeBackground (Message result) {
639        boolean success;
640
641        success = simulatedCallState.onChld('1', '\0');
642
643        if (!success){
644            resultFail(result, null, new RuntimeException("Hangup Error"));
645        } else {
646            resultSuccess(result, null);
647        }
648    }
649
650    /**
651     * 3GPP 22.030 6.5.5
652     * "Places all active calls (if any exist) on hold and accepts
653     *  the other (held or waiting) call."
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    @Override
660    public void switchWaitingOrHoldingAndActive (Message result) {
661        boolean success;
662
663        success = simulatedCallState.onChld('2', '\0');
664
665        if (!success){
666            resultFail(result, null, new RuntimeException("Hangup Error"));
667        } else {
668            resultSuccess(result, null);
669        }
670    }
671
672    /**
673     * 3GPP 22.030 6.5.5
674     * "Adds a held call to the conversation"
675     *
676     *  ar.exception carries exception on failure
677     *  ar.userObject contains the original value of result.obj
678     *  ar.result is null on success and failure
679     */
680    @Override
681    public void conference (Message result) {
682        boolean success;
683
684        success = simulatedCallState.onChld('3', '\0');
685
686        if (!success){
687            resultFail(result, null, new RuntimeException("Hangup Error"));
688        } else {
689            resultSuccess(result, null);
690        }
691    }
692
693    /**
694     * 3GPP 22.030 6.5.5
695     * "Connects the two calls and disconnects the subscriber from both calls"
696     *
697     *  ar.exception carries exception on failure
698     *  ar.userObject contains the original value of result.obj
699     *  ar.result is null on success and failure
700     */
701    @Override
702    public void explicitCallTransfer (Message result) {
703        boolean success;
704
705        success = simulatedCallState.onChld('4', '\0');
706
707        if (!success){
708            resultFail(result, null, new RuntimeException("Hangup Error"));
709        } else {
710            resultSuccess(result, null);
711        }
712    }
713
714    /**
715     * 3GPP 22.030 6.5.5
716     * "Places all active calls on hold except call X with which
717     *  communication shall be supported."
718     */
719    @Override
720    public void separateConnection (int gsmIndex, Message result) {
721        boolean success;
722
723        char ch = (char)(gsmIndex + '0');
724        success = simulatedCallState.onChld('2', ch);
725
726        if (!success){
727            resultFail(result, null, new RuntimeException("Hangup Error"));
728        } else {
729            resultSuccess(result, null);
730        }
731    }
732
733    /**
734     *
735     *  ar.exception carries exception on failure
736     *  ar.userObject contains the original value of result.obj
737     *  ar.result is null on success and failure
738     */
739    @Override
740    public void acceptCall (Message result) {
741        boolean success;
742
743        SimulatedCommandsVerifier.getInstance().acceptCall(result);
744        success = simulatedCallState.onAnswer();
745
746        if (!success){
747            resultFail(result, null, new RuntimeException("Hangup Error"));
748        } else {
749            resultSuccess(result, null);
750        }
751    }
752
753    /**
754     *  also known as UDUB
755     *  ar.exception carries exception on failure
756     *  ar.userObject contains the original value of result.obj
757     *  ar.result is null on success and failure
758     */
759    @Override
760    public void rejectCall (Message result) {
761        boolean success;
762
763        success = simulatedCallState.onChld('0', '\0');
764
765        if (!success){
766            resultFail(result, null, new RuntimeException("Hangup Error"));
767        } else {
768            resultSuccess(result, null);
769        }
770    }
771
772    /**
773     * cause code returned as Integer in Message.obj.response
774     * Returns integer cause code defined in TS 24.008
775     * Annex H or closest approximation.
776     * Most significant codes:
777     * - Any defined in 22.001 F.4 (for generating busy/congestion)
778     * - Cause 68: ACM >= ACMMax
779     */
780    @Override
781    public void getLastCallFailCause (Message result) {
782        LastCallFailCause mFailCause = new LastCallFailCause();
783        mFailCause.causeCode = mNextCallFailCause;
784        resultSuccess(result, mFailCause);
785    }
786
787    /**
788     * @deprecated
789     */
790    @Deprecated
791    @Override
792    public void getLastPdpFailCause (Message result) {
793        unimplemented(result);
794    }
795
796    @Override
797    public void getLastDataCallFailCause(Message result) {
798        //
799        unimplemented(result);
800    }
801
802    @Override
803    public void setMute (boolean enableMute, Message result) {unimplemented(result);}
804
805    @Override
806    public void getMute (Message result) {unimplemented(result);}
807
808    public void setSignalStrength(SignalStrength signalStrength) {
809        mSignalStrength = signalStrength;
810    }
811
812    @Override
813    public void getSignalStrength (Message result) {
814
815        if (mSignalStrength == null) {
816            mSignalStrength = new SignalStrength(
817                20, // gsmSignalStrength
818                0,  // gsmBitErrorRate
819                -1, // cdmaDbm
820                -1, // cdmaEcio
821                -1, // evdoDbm
822                -1, // evdoEcio
823                -1, // evdoSnr
824                99, // lteSignalStrength
825                SignalStrength.INVALID,     // lteRsrp
826                SignalStrength.INVALID,     // lteRsrq
827                SignalStrength.INVALID,     // lteRssnr
828                SignalStrength.INVALID,     // lteCqi
829                SignalStrength.INVALID,     // tdScdmaRscp
830                true                        // gsmFlag
831            );
832        }
833
834        resultSuccess(result, mSignalStrength);
835    }
836
837     /**
838     * Assign a specified band for RF configuration.
839     *
840     * @param bandMode one of BM_*_BAND
841     * @param result is callback message
842     */
843    @Override
844    public void setBandMode (int bandMode, Message result) {
845        resultSuccess(result, null);
846    }
847
848    /**
849     * Query the list of band mode supported by RF.
850     *
851     * @param result is callback message
852     *        ((AsyncResult)response.obj).result  is an int[] where int[0] is
853     *        the size of the array and the rest of each element representing
854     *        one available BM_*_BAND
855     */
856    @Override
857    public void queryAvailableBandMode (Message result) {
858        int ret[] = new int [4];
859
860        ret[0] = 4;
861        ret[1] = Phone.BM_US_BAND;
862        ret[2] = Phone.BM_JPN_BAND;
863        ret[3] = Phone.BM_AUS_BAND;
864
865        resultSuccess(result, ret);
866    }
867
868    /**
869     * {@inheritDoc}
870     */
871    @Override
872    public void sendTerminalResponse(String contents, Message response) {
873        resultSuccess(response, null);
874    }
875
876    /**
877     * {@inheritDoc}
878     */
879    @Override
880    public void sendEnvelope(String contents, Message response) {
881        resultSuccess(response, null);
882    }
883
884    /**
885     * {@inheritDoc}
886     */
887    @Override
888    public void sendEnvelopeWithStatus(String contents, Message response) {
889        resultSuccess(response, null);
890    }
891
892    /**
893     * {@inheritDoc}
894     */
895    @Override
896    public void handleCallSetupRequestFromSim(
897            boolean accept, Message response) {
898        resultSuccess(response, null);
899    }
900
901    public void setVoiceRadioTech(int voiceRadioTech) {
902        mVoiceRadioTech = voiceRadioTech;
903    }
904
905    public void setVoiceRegState(int voiceRegState) {
906        mVoiceRegState = voiceRegState;
907    }
908
909    /**
910     * response.obj.result is an String[14]
911     * See ril.h for details
912     *
913     * Please note that registration state 4 ("unknown") is treated
914     * as "out of service" above
915     */
916    @Override
917    public void getVoiceRegistrationState(Message result) {
918        mGetVoiceRegistrationStateCallCount.incrementAndGet();
919        String ret[] = new String[14];
920
921        ret[0] = Integer.toString(mVoiceRegState);
922        ret[3] = Integer.toString(mVoiceRadioTech);
923
924        resultSuccess(result, ret);
925    }
926
927    private final AtomicInteger mGetVoiceRegistrationStateCallCount = new AtomicInteger(0);
928
929    @VisibleForTesting
930    public int getGetVoiceRegistrationStateCallCount() {
931        return mGetVoiceRegistrationStateCallCount.get();
932    }
933
934    public void setDataRadioTech(int radioTech) {
935        mDataRadioTech = radioTech;
936    }
937
938    public void setDataRegState(int dataRegState) {
939        mDataRegState = dataRegState;
940    }
941
942    @Override
943    public void getDataRegistrationState (Message result) {
944        mGetDataRegistrationStateCallCount.incrementAndGet();
945        String ret[] = new String[11];
946
947        ret[0] = Integer.toString(mDataRegState);
948        ret[3] = Integer.toString(mDataRadioTech);
949
950        resultSuccess(result, ret);
951    }
952
953    private final AtomicInteger mGetDataRegistrationStateCallCount = new AtomicInteger(0);
954
955    @VisibleForTesting
956    public int getGetDataRegistrationStateCallCount() {
957        return mGetDataRegistrationStateCallCount.get();
958    }
959
960    /**
961     * response.obj.result is a String[3]
962     * response.obj.result[0] is long alpha or null if unregistered
963     * response.obj.result[1] is short alpha or null if unregistered
964     * response.obj.result[2] is numeric or null if unregistered
965     */
966    @Override
967    public void getOperator(Message result) {
968        mGetOperatorCallCount.incrementAndGet();
969        String[] ret = new String[3];
970
971        ret[0] = FAKE_LONG_NAME;
972        ret[1] = FAKE_SHORT_NAME;
973        ret[2] = FAKE_MCC_MNC;
974
975        resultSuccess(result, ret);
976    }
977
978    private final AtomicInteger mGetOperatorCallCount = new AtomicInteger(0);
979
980    @VisibleForTesting
981    public int getGetOperatorCallCount() {
982        final int count = mGetOperatorCallCount.get();
983        return mGetOperatorCallCount.get();
984    }
985
986    /**
987     *  ar.exception carries exception on failure
988     *  ar.userObject contains the original value of result.obj
989     *  ar.result is null on success and failure
990     */
991    @Override
992    public void sendDtmf(char c, Message result) {
993        resultSuccess(result, null);
994    }
995
996    /**
997     *  ar.exception carries exception on failure
998     *  ar.userObject contains the original value of result.obj
999     *  ar.result is null on success and failure
1000     */
1001    @Override
1002    public void startDtmf(char c, Message result) {
1003        resultSuccess(result, null);
1004    }
1005
1006    /**
1007     *  ar.exception carries exception on failure
1008     *  ar.userObject contains the original value of result.obj
1009     *  ar.result is null on success and failure
1010     */
1011    @Override
1012    public void stopDtmf(Message result) {
1013        resultSuccess(result, null);
1014    }
1015
1016    /**
1017     *  ar.exception carries exception on failure
1018     *  ar.userObject contains the original value of result.obj
1019     *  ar.result is null on success and failure
1020     */
1021    @Override
1022    public void sendBurstDtmf(String dtmfString, int on, int off, Message result) {
1023        SimulatedCommandsVerifier.getInstance().sendBurstDtmf(dtmfString, on, off, result);
1024        resultSuccess(result, null);
1025    }
1026
1027    /**
1028     * smscPDU is smsc address in PDU form GSM BCD format prefixed
1029     *      by a length byte (as expected by TS 27.005) or NULL for default SMSC
1030     * pdu is SMS in PDU format as an ASCII hex string
1031     *      less the SMSC address
1032     */
1033    @Override
1034    public void sendSMS (String smscPDU, String pdu, Message result) {
1035        SimulatedCommandsVerifier.getInstance().sendSMS(smscPDU, pdu, result);
1036        resultSuccess(result, new SmsResponse(0 /*messageRef*/, null, 0));
1037    }
1038
1039    /**
1040     * Send an SMS message, Identical to sendSMS,
1041     * except that more messages are expected to be sent soon
1042     * smscPDU is smsc address in PDU form GSM BCD format prefixed
1043     *      by a length byte (as expected by TS 27.005) or NULL for default SMSC
1044     * pdu is SMS in PDU format as an ASCII hex string
1045     *      less the SMSC address
1046     */
1047    @Override
1048    public void sendSMSExpectMore (String smscPDU, String pdu, Message result) {
1049        unimplemented(result);
1050    }
1051
1052    @Override
1053    public void deleteSmsOnSim(int index, Message response) {
1054        Rlog.d(LOG_TAG, "Delete message at index " + index);
1055        unimplemented(response);
1056    }
1057
1058    @Override
1059    public void deleteSmsOnRuim(int index, Message response) {
1060        Rlog.d(LOG_TAG, "Delete RUIM message at index " + index);
1061        unimplemented(response);
1062    }
1063
1064    @Override
1065    public void writeSmsToSim(int status, String smsc, String pdu, Message response) {
1066        Rlog.d(LOG_TAG, "Write SMS to SIM with status " + status);
1067        unimplemented(response);
1068    }
1069
1070    @Override
1071    public void writeSmsToRuim(int status, String pdu, Message response) {
1072        Rlog.d(LOG_TAG, "Write SMS to RUIM with status " + status);
1073        unimplemented(response);
1074    }
1075
1076    public void setDataCallResponse(final boolean success, final DataCallResponse dcResponse) {
1077        mDcResponse = dcResponse;
1078        mDcSuccess = success;
1079    }
1080
1081    public void triggerNITZupdate(String NITZStr) {
1082        if (NITZStr != null) {
1083            mNITZTimeRegistrant.notifyRegistrant(new AsyncResult (null, new Object[]{NITZStr,
1084                    SystemClock.elapsedRealtime()}, null));
1085        }
1086    }
1087
1088    @Override
1089    public void setupDataCall(int radioTechnology, int profile,
1090            String apn, String user, String password, int authType,
1091            String protocol, Message result) {
1092        SimulatedCommandsVerifier.getInstance().setupDataCall(radioTechnology, profile, apn, user,
1093                password, authType, protocol, result);
1094
1095        if (mDcResponse == null) {
1096            mDcResponse = new DataCallResponse();
1097            mDcResponse.version = 11;
1098            mDcResponse.status = 0;
1099            mDcResponse.suggestedRetryTime = -1;
1100            mDcResponse.cid = 1;
1101            mDcResponse.active = 2;
1102            mDcResponse.type = "IP";
1103            mDcResponse.ifname = "rmnet_data7";
1104            mDcResponse.mtu = 1440;
1105            mDcResponse.addresses = new String[]{"12.34.56.78"};
1106            mDcResponse.dnses = new String[]{"98.76.54.32"};
1107            mDcResponse.gateways = new String[]{"11.22.33.44"};
1108            mDcResponse.pcscf = new String[]{};
1109        }
1110
1111        if (mDcSuccess) {
1112            resultSuccess(result, mDcResponse);
1113        } else {
1114            resultFail(result, mDcResponse, new RuntimeException("Setup data call failed!"));
1115        }
1116    }
1117
1118    @Override
1119    public void deactivateDataCall(int cid, int reason, Message result) {
1120        SimulatedCommandsVerifier.getInstance().deactivateDataCall(cid, reason, result);
1121        resultSuccess(result, null);
1122    }
1123
1124    @Override
1125    public void setPreferredNetworkType(int networkType , Message result) {
1126        SimulatedCommandsVerifier.getInstance().setPreferredNetworkType(networkType, result);
1127        mNetworkType = networkType;
1128        resultSuccess(result, null);
1129    }
1130
1131    @Override
1132    public void getPreferredNetworkType(Message result) {
1133        SimulatedCommandsVerifier.getInstance().getPreferredNetworkType(result);
1134        int ret[] = new int[1];
1135
1136        ret[0] = mNetworkType;
1137        resultSuccess(result, ret);
1138    }
1139
1140    @Override
1141    public void getNeighboringCids(Message result) {
1142        int ret[] = new int[7];
1143
1144        ret[0] = 6;
1145        for (int i = 1; i<7; i++) {
1146            ret[i] = i;
1147        }
1148        resultSuccess(result, ret);
1149    }
1150
1151    @Override
1152    public void setLocationUpdates(boolean enable, Message response) {
1153        SimulatedCommandsVerifier.getInstance().setLocationUpdates(enable, response);
1154        resultSuccess(response, null);
1155    }
1156
1157    @Override
1158    public void getSmscAddress(Message result) {
1159        unimplemented(result);
1160    }
1161
1162    @Override
1163    public void setSmscAddress(String address, Message result) {
1164        unimplemented(result);
1165    }
1166
1167    @Override
1168    public void reportSmsMemoryStatus(boolean available, Message result) {
1169        resultSuccess(result, null);
1170        SimulatedCommandsVerifier.getInstance().reportSmsMemoryStatus(available, result);
1171    }
1172
1173    @Override
1174    public void reportStkServiceIsRunning(Message result) {
1175        resultSuccess(result, null);
1176    }
1177
1178    @Override
1179    public void getCdmaSubscriptionSource(Message result) {
1180        unimplemented(result);
1181    }
1182
1183    private boolean isSimLocked() {
1184        if (mSimLockedState != SimLockState.NONE) {
1185            return true;
1186        }
1187        return false;
1188    }
1189
1190    @Override
1191    public void setRadioPower(boolean on, Message result) {
1192        if(on) {
1193            setRadioState(RadioState.RADIO_ON);
1194        } else {
1195            setRadioState(RadioState.RADIO_OFF);
1196        }
1197    }
1198
1199
1200    @Override
1201    public void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) {
1202        unimplemented(result);
1203        SimulatedCommandsVerifier.getInstance().
1204                acknowledgeLastIncomingGsmSms(success, cause, result);
1205    }
1206
1207    @Override
1208    public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) {
1209        unimplemented(result);
1210    }
1211
1212    @Override
1213    public void acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu,
1214            Message result) {
1215        unimplemented(result);
1216    }
1217
1218    @Override
1219    public void iccIO(int command, int fileid, String path, int p1, int p2, int p3, String data,
1220            String pin2, Message response) {
1221        iccIOForApp(command, fileid, path, p1, p2, p3, data, pin2, null, response);
1222    }
1223
1224    /**
1225     * parameters equivalent to 27.007 AT+CRSM command
1226     * response.obj will be an AsyncResult
1227     * response.obj.userObj will be a SimIoResult on success
1228     */
1229    @Override
1230    public void iccIOForApp (int command, int fileid, String path, int p1, int p2,
1231                       int p3, String data, String pin2, String aid, Message result) {
1232        unimplemented(result);
1233    }
1234
1235    /**
1236     * (AsyncResult)response.obj).result is an int[] with element [0] set to
1237     * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned".
1238     *
1239     * @param response is callback message
1240     */
1241    @Override
1242    public void queryCLIP(Message response) { unimplemented(response); }
1243
1244
1245    /**
1246     * response.obj will be a an int[2]
1247     *
1248     * response.obj[0] will be TS 27.007 +CLIR parameter 'n'
1249     *  0 presentation indicator is used according to the subscription of the CLIR service
1250     *  1 CLIR invocation
1251     *  2 CLIR suppression
1252     *
1253     * response.obj[1] will be TS 27.007 +CLIR parameter 'm'
1254     *  0 CLIR not provisioned
1255     *  1 CLIR provisioned in permanent mode
1256     *  2 unknown (e.g. no network, etc.)
1257     *  3 CLIR temporary mode presentation restricted
1258     *  4 CLIR temporary mode presentation allowed
1259     */
1260
1261    @Override
1262    public void getCLIR(Message result) {unimplemented(result);}
1263
1264    /**
1265     * clirMode is one of the CLIR_* constants above
1266     *
1267     * response.obj is null
1268     */
1269
1270    @Override
1271    public void setCLIR(int clirMode, Message result) {unimplemented(result);}
1272
1273    /**
1274     * (AsyncResult)response.obj).result is an int[] with element [0] set to
1275     * 0 for disabled, 1 for enabled.
1276     *
1277     * @param serviceClass is a sum of SERVICE_CLASS_*
1278     * @param response is callback message
1279     */
1280
1281    @Override
1282    public void queryCallWaiting(int serviceClass, Message response) {
1283        unimplemented(response);
1284    }
1285
1286    /**
1287     * @param enable is true to enable, false to disable
1288     * @param serviceClass is a sum of SERVICE_CLASS_*
1289     * @param response is callback message
1290     */
1291
1292    @Override
1293    public void setCallWaiting(boolean enable, int serviceClass,
1294            Message response) {
1295        unimplemented(response);
1296    }
1297
1298    /**
1299     * @param action is one of CF_ACTION_*
1300     * @param cfReason is one of CF_REASON_*
1301     * @param serviceClass is a sum of SERVICE_CLASSS_*
1302     */
1303    @Override
1304    public void setCallForward(int action, int cfReason, int serviceClass,
1305            String number, int timeSeconds, Message result) {
1306        SimulatedCommandsVerifier.getInstance().setCallForward(action, cfReason, serviceClass,
1307                number, timeSeconds, result);
1308        resultSuccess(result, null);
1309    }
1310
1311    /**
1312     * cfReason is one of CF_REASON_*
1313     *
1314     * ((AsyncResult)response.obj).result will be an array of
1315     * CallForwardInfo's
1316     *
1317     * An array of length 0 means "disabled for all codes"
1318     */
1319    @Override
1320    public void queryCallForwardStatus(int cfReason, int serviceClass,
1321            String number, Message result) {
1322        SimulatedCommandsVerifier.getInstance().queryCallForwardStatus(cfReason, serviceClass,
1323                number, result);
1324        resultSuccess(result, null);
1325    }
1326
1327    @Override
1328    public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);}
1329    @Override
1330    public void exitEmergencyCallbackMode(Message result) {unimplemented(result);}
1331    @Override
1332    public void setNetworkSelectionModeManual(
1333            String operatorNumeric, Message result) {unimplemented(result);}
1334
1335    /**
1336     * Queries whether the current network selection mode is automatic
1337     * or manual
1338     *
1339     * ((AsyncResult)response.obj).result  is an int[] with element [0] being
1340     * a 0 for automatic selection and a 1 for manual selection
1341     */
1342
1343    @Override
1344    public void getNetworkSelectionMode(Message result) {
1345        SimulatedCommandsVerifier.getInstance().getNetworkSelectionMode(result);
1346        getNetworkSelectionModeCallCount.incrementAndGet();
1347        int ret[] = new int[1];
1348
1349        ret[0] = 0;
1350        resultSuccess(result, ret);
1351    }
1352
1353    private final AtomicInteger getNetworkSelectionModeCallCount = new AtomicInteger(0);
1354
1355    @VisibleForTesting
1356    public int getGetNetworkSelectionModeCallCount() {
1357        return getNetworkSelectionModeCallCount.get();
1358    }
1359
1360    /**
1361     * Queries the currently available networks
1362     *
1363     * ((AsyncResult)response.obj).result  is a List of NetworkInfo objects
1364     */
1365    @Override
1366    public void getAvailableNetworks(Message result) {unimplemented(result);}
1367
1368    @Override
1369    public void getBasebandVersion (Message result) {
1370        SimulatedCommandsVerifier.getInstance().getBasebandVersion(result);
1371        resultSuccess(result, "SimulatedCommands");
1372    }
1373
1374    /**
1375     * Simulates an Stk Call Control Alpha message
1376     * @param alphaString Alpha string to send.
1377     */
1378    public void triggerIncomingStkCcAlpha(String alphaString) {
1379        if (mCatCcAlphaRegistrant != null) {
1380            mCatCcAlphaRegistrant.notifyResult(alphaString);
1381        }
1382    }
1383
1384    public void sendStkCcAplha(String alphaString) {
1385        triggerIncomingStkCcAlpha(alphaString);
1386    }
1387
1388    /**
1389     * Simulates an incoming USSD message
1390     * @param statusCode  Status code string. See <code>setOnUSSD</code>
1391     * in CommandsInterface.java
1392     * @param message Message text to send or null if none
1393     */
1394    @Override
1395    public void triggerIncomingUssd(String statusCode, String message) {
1396        if (mUSSDRegistrant != null) {
1397            String[] result = {statusCode, message};
1398            mUSSDRegistrant.notifyResult(result);
1399        }
1400    }
1401
1402
1403    @Override
1404    public void sendUSSD (String ussdString, Message result) {
1405
1406        // We simulate this particular sequence
1407        if (ussdString.equals("#646#")) {
1408            resultSuccess(result, null);
1409
1410            // 0 == USSD-Notify
1411            triggerIncomingUssd("0", "You have NNN minutes remaining.");
1412        } else {
1413            resultSuccess(result, null);
1414
1415            triggerIncomingUssd("0", "All Done");
1416        }
1417    }
1418
1419    // inherited javadoc suffices
1420    @Override
1421    public void cancelPendingUssd (Message response) {
1422        resultSuccess(response, null);
1423    }
1424
1425
1426    @Override
1427    public void resetRadio(Message result) {
1428        unimplemented(result);
1429    }
1430
1431    @Override
1432    public void invokeOemRilRequestRaw(byte[] data, Message response) {
1433        // Just echo back data
1434        if (response != null) {
1435            AsyncResult.forMessage(response).result = data;
1436            response.sendToTarget();
1437        }
1438    }
1439
1440    @Override
1441    public void invokeOemRilRequestStrings(String[] strings, Message response) {
1442        // Just echo back data
1443        if (response != null) {
1444            AsyncResult.forMessage(response).result = strings;
1445            response.sendToTarget();
1446        }
1447    }
1448
1449    //***** SimulatedRadioControl
1450
1451
1452    /** Start the simulated phone ringing */
1453    @Override
1454    public void
1455    triggerRing(String number) {
1456        simulatedCallState.triggerRing(number);
1457        mCallStateRegistrants.notifyRegistrants();
1458    }
1459
1460    @Override
1461    public void
1462    progressConnectingCallState() {
1463        simulatedCallState.progressConnectingCallState();
1464        mCallStateRegistrants.notifyRegistrants();
1465    }
1466
1467    /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */
1468    @Override
1469    public void
1470    progressConnectingToActive() {
1471        simulatedCallState.progressConnectingToActive();
1472        mCallStateRegistrants.notifyRegistrants();
1473    }
1474
1475    /** automatically progress mobile originated calls to ACTIVE.
1476     *  default to true
1477     */
1478    @Override
1479    public void
1480    setAutoProgressConnectingCall(boolean b) {
1481        simulatedCallState.setAutoProgressConnectingCall(b);
1482    }
1483
1484    @Override
1485    public void
1486    setNextDialFailImmediately(boolean b) {
1487        simulatedCallState.setNextDialFailImmediately(b);
1488    }
1489
1490    @Override
1491    public void
1492    setNextCallFailCause(int gsmCause) {
1493        mNextCallFailCause = gsmCause;
1494    }
1495
1496    @Override
1497    public void
1498    triggerHangupForeground() {
1499        simulatedCallState.triggerHangupForeground();
1500        mCallStateRegistrants.notifyRegistrants();
1501    }
1502
1503    /** hangup holding calls */
1504    @Override
1505    public void
1506    triggerHangupBackground() {
1507        simulatedCallState.triggerHangupBackground();
1508        mCallStateRegistrants.notifyRegistrants();
1509    }
1510
1511    @Override
1512    public void triggerSsn(int type, int code) {
1513        SuppServiceNotification not = new SuppServiceNotification();
1514        not.notificationType = type;
1515        not.code = code;
1516        mSsnRegistrant.notifyRegistrant(new AsyncResult(null, not, null));
1517    }
1518
1519    @Override
1520    public void
1521    shutdown() {
1522        setRadioState(RadioState.RADIO_UNAVAILABLE);
1523        Looper looper = mHandlerThread.getLooper();
1524        if (looper != null) {
1525            looper.quit();
1526        }
1527    }
1528
1529    /** hangup all */
1530
1531    @Override
1532    public void
1533    triggerHangupAll() {
1534        simulatedCallState.triggerHangupAll();
1535        mCallStateRegistrants.notifyRegistrants();
1536    }
1537
1538    @Override
1539    public void
1540    triggerIncomingSMS(String message) {
1541        //TODO
1542    }
1543
1544    @Override
1545    public void
1546    pauseResponses() {
1547        mPausedResponseCount++;
1548    }
1549
1550    @Override
1551    public void
1552    resumeResponses() {
1553        mPausedResponseCount--;
1554
1555        if (mPausedResponseCount == 0) {
1556            for (int i = 0, s = mPausedResponses.size(); i < s ; i++) {
1557                mPausedResponses.get(i).sendToTarget();
1558            }
1559            mPausedResponses.clear();
1560        } else {
1561            Rlog.e("GSM", "SimulatedCommands.resumeResponses < 0");
1562        }
1563    }
1564
1565    //***** Private Methods
1566
1567    private void unimplemented(Message result) {
1568        if (result != null) {
1569            AsyncResult.forMessage(result).exception
1570                = new RuntimeException("Unimplemented");
1571
1572            if (mPausedResponseCount > 0) {
1573                mPausedResponses.add(result);
1574            } else {
1575                result.sendToTarget();
1576            }
1577        }
1578    }
1579
1580    private void resultSuccess(Message result, Object ret) {
1581        if (result != null) {
1582            AsyncResult.forMessage(result).result = ret;
1583            if (mPausedResponseCount > 0) {
1584                mPausedResponses.add(result);
1585            } else {
1586                result.sendToTarget();
1587            }
1588        }
1589    }
1590
1591    private void resultFail(Message result, Object ret, Throwable tr) {
1592        if (result != null) {
1593            AsyncResult.forMessage(result, ret, tr);
1594            if (mPausedResponseCount > 0) {
1595                mPausedResponses.add(result);
1596            } else {
1597                result.sendToTarget();
1598            }
1599        }
1600    }
1601
1602    // ***** Methods for CDMA support
1603    @Override
1604    public void
1605    getDeviceIdentity(Message response) {
1606        SimulatedCommandsVerifier.getInstance().getDeviceIdentity(response);
1607        resultSuccess(response, new String[] {FAKE_IMEI, FAKE_IMEISV, FAKE_ESN, FAKE_MEID});
1608    }
1609
1610    @Override
1611    public void
1612    getCDMASubscription(Message result) {
1613        String ret[] = new String[5];
1614        ret[0] = "123";
1615        ret[1] = "456";
1616        ret[2] = "789";
1617        ret[3] = "234";
1618        ret[4] = "345";
1619        resultSuccess(result, ret);
1620    }
1621
1622    @Override
1623    public void
1624    setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response) {
1625        unimplemented(response);
1626    }
1627
1628    @Override
1629    public void queryCdmaRoamingPreference(Message response) {
1630        unimplemented(response);
1631    }
1632
1633    @Override
1634    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
1635        unimplemented(response);
1636    }
1637
1638    @Override
1639    public void
1640    setPhoneType(int phoneType) {
1641    }
1642
1643    @Override
1644    public void getPreferredVoicePrivacy(Message result) {
1645        unimplemented(result);
1646    }
1647
1648    @Override
1649    public void setPreferredVoicePrivacy(boolean enable, Message result) {
1650        unimplemented(result);
1651    }
1652
1653    /**
1654     *  Set the TTY mode
1655     *
1656     * @param ttyMode is one of the following:
1657     * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF}
1658     * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL}
1659     * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO}
1660     * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
1661     * @param response is callback message
1662     */
1663    @Override
1664    public void setTTYMode(int ttyMode, Message response) {
1665        Rlog.w(LOG_TAG, "Not implemented in SimulatedCommands");
1666        unimplemented(response);
1667    }
1668
1669    /**
1670     *  Query the TTY mode
1671     * (AsyncResult)response.obj).result is an int[] with element [0] set to
1672     * tty mode:
1673     * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF}
1674     * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL}
1675     * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO}
1676     * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
1677     * @param response is callback message
1678     */
1679    @Override
1680    public void queryTTYMode(Message response) {
1681        unimplemented(response);
1682    }
1683
1684    /**
1685     * {@inheritDoc}
1686     */
1687    @Override
1688    public void sendCDMAFeatureCode(String FeatureCode, Message response) {
1689        unimplemented(response);
1690    }
1691
1692    /**
1693     * {@inheritDoc}
1694     */
1695    @Override
1696    public void sendCdmaSms(byte[] pdu, Message response){
1697        SimulatedCommandsVerifier.getInstance().sendCdmaSms(pdu, response);
1698        resultSuccess(response, null);
1699    }
1700
1701    @Override
1702    public void setCdmaBroadcastActivation(boolean activate, Message response) {
1703        unimplemented(response);
1704
1705    }
1706
1707    @Override
1708    public void getCdmaBroadcastConfig(Message response) {
1709        unimplemented(response);
1710
1711    }
1712
1713    @Override
1714    public void setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs, Message response) {
1715        unimplemented(response);
1716    }
1717
1718    public void forceDataDormancy(Message response) {
1719        unimplemented(response);
1720    }
1721
1722
1723    @Override
1724    public void setGsmBroadcastActivation(boolean activate, Message response) {
1725        unimplemented(response);
1726    }
1727
1728
1729    @Override
1730    public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) {
1731        unimplemented(response);
1732    }
1733
1734    @Override
1735    public void getGsmBroadcastConfig(Message response) {
1736        unimplemented(response);
1737    }
1738
1739    @Override
1740    public void supplyIccPinForApp(String pin, String aid, Message response) {
1741        SimulatedCommandsVerifier.getInstance().supplyIccPinForApp(pin, aid, response);
1742        if (mPinCode != null && mPinCode.equals(pin)) {
1743            resultSuccess(response, null);
1744            return;
1745        }
1746
1747        Rlog.i(LOG_TAG, "[SimCmd] supplyIccPinForApp: pin failed!");
1748        CommandException ex = new CommandException(
1749                CommandException.Error.PASSWORD_INCORRECT);
1750        resultFail(response, new int[]{
1751                (--mPin1attemptsRemaining < 0) ? 0 : mPin1attemptsRemaining}, ex);
1752    }
1753
1754    @Override
1755    public void supplyIccPukForApp(String puk, String newPin, String aid, Message response) {
1756        unimplemented(response);
1757    }
1758
1759    @Override
1760    public void supplyIccPin2ForApp(String pin2, String aid, Message response) {
1761        unimplemented(response);
1762    }
1763
1764    @Override
1765    public void supplyIccPuk2ForApp(String puk2, String newPin2, String aid, Message response) {
1766        unimplemented(response);
1767    }
1768
1769    @Override
1770    public void changeIccPinForApp(String oldPin, String newPin, String aidPtr, Message response) {
1771        SimulatedCommandsVerifier.getInstance().changeIccPinForApp(oldPin, newPin, aidPtr,
1772                response);
1773        changeIccPin(oldPin, newPin, response);
1774    }
1775
1776    @Override
1777    public void changeIccPin2ForApp(String oldPin2, String newPin2, String aidPtr,
1778            Message response) {
1779        unimplemented(response);
1780    }
1781
1782    @Override
1783    public void requestIsimAuthentication(String nonce, Message response) {
1784        unimplemented(response);
1785    }
1786
1787    @Override
1788    public void requestIccSimAuthentication(int authContext, String data, String aid, Message response) {
1789        unimplemented(response);
1790    }
1791
1792    @Override
1793    public void getVoiceRadioTechnology(Message response) {
1794        SimulatedCommandsVerifier.getInstance().getVoiceRadioTechnology(response);
1795        int ret[] = new int[1];
1796        ret[0] = mVoiceRadioTech;
1797        resultSuccess(response, ret);
1798    }
1799
1800    public void setCellInfoList(List<CellInfo> list) {
1801        mCellInfoList = list;
1802    }
1803
1804    @Override
1805    public void getCellInfoList(Message response) {
1806        if (mCellInfoList == null) {
1807            Parcel p = Parcel.obtain();
1808            p.writeInt(1);
1809            p.writeInt(1);
1810            p.writeInt(2);
1811            p.writeLong(1453510289108L);
1812            p.writeInt(310);
1813            p.writeInt(260);
1814            p.writeInt(123);
1815            p.writeInt(456);
1816            p.writeInt(99);
1817            p.writeInt(3);
1818            p.setDataPosition(0);
1819
1820            CellInfoGsm cellInfo = CellInfoGsm.CREATOR.createFromParcel(p);
1821
1822            ArrayList<CellInfo> mCellInfoList = new ArrayList();
1823            mCellInfoList.add(cellInfo);
1824        }
1825
1826        resultSuccess(response, mCellInfoList);
1827    }
1828
1829    @Override
1830    public int getRilVersion() {
1831        return 11;
1832    }
1833
1834    @Override
1835    public void setCellInfoListRate(int rateInMillis, Message response) {
1836        unimplemented(response);
1837    }
1838
1839    @Override
1840    public void setInitialAttachApn(String apn, String protocol, int authType, String username,
1841            String password, Message result) {
1842    }
1843
1844    @Override
1845    public void setDataProfile(DataProfile[] dps, Message result) {
1846    }
1847
1848    public void setImsRegistrationState(int[] regState) {
1849        mImsRegState = regState;
1850    }
1851
1852    @Override
1853    public void getImsRegistrationState(Message response) {
1854        if (mImsRegState == null) {
1855            mImsRegState = new int[]{1, PhoneConstants.PHONE_TYPE_NONE};
1856        }
1857
1858        resultSuccess(response, mImsRegState);
1859    }
1860
1861    @Override
1862    public void sendImsCdmaSms(byte[] pdu, int retry, int messageRef,
1863            Message response){
1864        SimulatedCommandsVerifier.getInstance().sendImsCdmaSms(pdu, retry, messageRef, response);
1865        resultSuccess(response, new SmsResponse(0 /*messageRef*/, null, 0));
1866    }
1867
1868    @Override
1869    public void sendImsGsmSms(String smscPDU, String pdu,
1870            int retry, int messageRef, Message response){
1871        SimulatedCommandsVerifier.getInstance().sendImsGsmSms(smscPDU, pdu, retry, messageRef,
1872                response);
1873        resultSuccess(response, new SmsResponse(0 /*messageRef*/, null, 0));
1874    }
1875
1876    @Override
1877    public void iccOpenLogicalChannel(String AID, Message response) {
1878        SimulatedCommandsVerifier.getInstance().iccOpenLogicalChannel(AID, response);
1879        Object result = new int[]{mChannelId};
1880        resultSuccess(response, result);
1881    }
1882
1883    @Override
1884    public void iccCloseLogicalChannel(int channel, Message response) {
1885        unimplemented(response);
1886    }
1887
1888    @Override
1889    public void iccTransmitApduLogicalChannel(int channel, int cla, int instruction,
1890                                              int p1, int p2, int p3, String data,
1891                                              Message response) {
1892        SimulatedCommandsVerifier.getInstance().iccTransmitApduLogicalChannel(channel, cla,
1893                instruction, p1, p2, p3, data, response);
1894        if(mIccIoResultForApduLogicalChannel!=null) {
1895            resultSuccess(response, mIccIoResultForApduLogicalChannel);
1896        }else {
1897            resultFail(response, null, new RuntimeException("IccIoResult not set"));
1898        }
1899    }
1900
1901    @Override
1902    public void iccTransmitApduBasicChannel(int cla, int instruction, int p1, int p2,
1903            int p3, String data, Message response) {
1904        unimplemented(response);
1905    }
1906
1907    @Override
1908    public void nvReadItem(int itemID, Message response) {
1909        unimplemented(response);
1910    }
1911
1912    @Override
1913    public void nvWriteItem(int itemID, String itemValue, Message response) {
1914        unimplemented(response);
1915    }
1916
1917    @Override
1918    public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message response) {
1919        unimplemented(response);
1920    }
1921
1922    @Override
1923    public void nvResetConfig(int resetType, Message response) {
1924        unimplemented(response);
1925    }
1926
1927    @Override
1928    public void getHardwareConfig(Message result) {
1929        unimplemented(result);
1930    }
1931
1932    @Override
1933    public void requestShutdown(Message result) {
1934        setRadioState(RadioState.RADIO_UNAVAILABLE);
1935    }
1936
1937    @Override
1938    public void startLceService(int report_interval_ms, boolean pullMode, Message result) {
1939        SimulatedCommandsVerifier.getInstance().startLceService(report_interval_ms, pullMode,
1940                result);
1941        unimplemented(result);
1942    }
1943
1944    @Override
1945    public void stopLceService(Message result) {
1946        unimplemented(result);
1947    }
1948
1949    @Override
1950    public void pullLceData(Message result) {
1951        unimplemented(result);
1952    }
1953
1954    @Override
1955    public void getModemActivityInfo(Message result) {
1956        unimplemented(result);
1957    }
1958
1959    @Override
1960    public void getRadioCapability(Message result) {
1961        SimulatedCommandsVerifier.getInstance().getRadioCapability(result);
1962        resultSuccess(result, new RadioCapability(0, 0, 0, 0xFFFF, null, 0));
1963    }
1964    public void notifySmsStatus(Object result) {
1965        if (mSmsStatusRegistrant != null) {
1966            mSmsStatusRegistrant.notifyRegistrant(new AsyncResult(null, result, null));
1967        }
1968    }
1969
1970    public void notifyGsmBroadcastSms(Object result) {
1971        if (mGsmBroadcastSmsRegistrant != null) {
1972            mGsmBroadcastSmsRegistrant.notifyRegistrant(new AsyncResult(null, result, null));
1973        }
1974    }
1975
1976    public void notifyIccSmsFull() {
1977        if (mIccSmsFullRegistrant != null) {
1978            mIccSmsFullRegistrant.notifyRegistrant();
1979        }
1980    }
1981
1982    public void notifyEmergencyCallbackMode() {
1983        if (mEmergencyCallbackModeRegistrant != null) {
1984            mEmergencyCallbackModeRegistrant.notifyRegistrant();
1985        }
1986    }
1987
1988    @Override
1989    public void setEmergencyCallbackMode(Handler h, int what, Object obj) {
1990        SimulatedCommandsVerifier.getInstance().setEmergencyCallbackMode(h, what, obj);
1991        super.setEmergencyCallbackMode(h, what, obj);
1992    }
1993
1994    public void notifyExitEmergencyCallbackMode() {
1995        if (mExitEmergencyCallbackModeRegistrants != null) {
1996            mExitEmergencyCallbackModeRegistrants.notifyRegistrants(
1997                    new AsyncResult (null, null, null));
1998        }
1999    }
2000
2001    public void notifyImsNetworkStateChanged() {
2002        if(mImsNetworkStateChangedRegistrants != null) {
2003            mImsNetworkStateChangedRegistrants.notifyRegistrants();
2004        }
2005    }
2006
2007    @Override
2008    public void registerForExitEmergencyCallbackMode(Handler h, int what, Object obj) {
2009        SimulatedCommandsVerifier.getInstance().registerForExitEmergencyCallbackMode(h, what, obj);
2010        super.registerForExitEmergencyCallbackMode(h, what, obj);
2011    }
2012
2013    public void notifyRadioOn() {
2014        mOnRegistrants.notifyRegistrants();
2015    }
2016
2017    @VisibleForTesting
2018    public void notifyVoiceNetworkStateChanged() {
2019        mVoiceNetworkStateRegistrants.notifyRegistrants();
2020    }
2021
2022    @VisibleForTesting
2023    public void notifyOtaProvisionStatusChanged() {
2024        if (mOtaProvisionRegistrants != null) {
2025            int ret[] = new int[1];
2026            ret[0] = Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED;
2027            mOtaProvisionRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));
2028        }
2029    }
2030
2031    public void notifySignalStrength() {
2032        if (mSignalStrength == null) {
2033            mSignalStrength = new SignalStrength(
2034                    20, // gsmSignalStrength
2035                    0,  // gsmBitErrorRate
2036                    -1, // cdmaDbm
2037                    -1, // cdmaEcio
2038                    -1, // evdoDbm
2039                    -1, // evdoEcio
2040                    -1, // evdoSnr
2041                    99, // lteSignalStrength
2042                    SignalStrength.INVALID,     // lteRsrp
2043                    SignalStrength.INVALID,     // lteRsrq
2044                    SignalStrength.INVALID,     // lteRssnr
2045                    SignalStrength.INVALID,     // lteCqi
2046                    SignalStrength.INVALID,     // tdScdmaRscp
2047                    true                        // gsmFlag
2048            );
2049        }
2050
2051        if (mSignalStrengthRegistrant != null) {
2052            mSignalStrengthRegistrant.notifyRegistrant(
2053                    new AsyncResult (null, mSignalStrength, null));
2054        }
2055    }
2056
2057    public void setIccCardStatus(IccCardStatus iccCardStatus){
2058        mIccCardStatus = iccCardStatus;
2059    }
2060
2061    public void setIccIoResultForApduLogicalChannel(IccIoResult iccIoResult) {
2062        mIccIoResultForApduLogicalChannel = iccIoResult;
2063    }
2064
2065    public void setOpenChannelId(int channelId) {
2066        mChannelId = channelId;
2067    }
2068
2069    public void setPin1RemainingAttempt(int pin1attemptsRemaining) {
2070        mPin1attemptsRemaining = pin1attemptsRemaining;
2071    }
2072
2073    private AtomicBoolean mAllowed = new AtomicBoolean(false);
2074
2075    @Override
2076    public void setDataAllowed(boolean allowed, Message result) {
2077        log("setDataAllowed = " + allowed);
2078        mAllowed.set(allowed);
2079        resultSuccess(result, null);
2080    }
2081
2082    @VisibleForTesting
2083    public boolean isDataAllowed() {
2084        return mAllowed.get();
2085    }
2086}
2087