10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2006 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.test;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.HandlerThread;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Looper;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.IOException;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.InputStream;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.OutputStream;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.UnsupportedEncodingException;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.net.InetSocketAddress;
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.net.ServerSocket;
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.net.Socket;
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List;
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville// Also in ATChannel.java
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleclass LineReader
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Not threadsafe
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Assumes input is ASCII
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Constants
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // For what it's worth, this is also the size of an
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // OMAP CSMI mailbox
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int BUFFER_SIZE = 0x1000;
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // just to prevent constant allocations
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    byte buffer[] = new byte[BUFFER_SIZE];
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Instance Variables
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    InputStream inStream;
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    LineReader (InputStream s)
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        inStream = s;
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    getNextLine()
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return getNextLine(false);
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    getNextLineCtrlZ()
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return getNextLine(true);
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: doesn't return the last incomplete line read on EOF, since
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * it doesn't typically matter anyway
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns NULL on EOF
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    getNextLine(boolean ctrlZ)
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int i = 0;
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (;;) {
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int result;
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                result = inStream.read();
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (result < 0) {
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    return null;
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ctrlZ && result == 0x1a) {
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (result == '\r' || result == '\n') {
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (i == 0) {
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Skip leading cr/lf
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        continue;
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                buffer[i++] = (byte)result;
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IOException ex) {
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IndexOutOfBoundsException ex) {
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            System.err.println("ATChannel: buffer overflow");
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return new String(buffer, 0, i, "US-ASCII");
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (UnsupportedEncodingException ex) {
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            System.err.println("ATChannel: implausable UnsupportedEncodingException");
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleclass InterpreterEx extends Exception
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    InterpreterEx (String result)
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.result = result;
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String result;
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class ModelInterpreter
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            implements Runnable, SimulatedRadioControl
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MAX_CALLS = 6;
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** number of msec between dialing -> alerting and alerting->active */
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int CONNECTING_PAUSE_MSEC = 5 * 100;
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final String LOG_TAG = "ModelInterpreter";
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Instance Variables
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    InputStream in;
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    OutputStream out;
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    LineReader lineReader;
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    ServerSocket ss;
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private String finalResponse;
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SimulatedGsmCallState simulatedCallState;
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    HandlerThread mHandlerThread;
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    int pausedResponseCount;
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    Object pausedResponseMonitor = new Object();
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Events
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int PROGRESS_CALL_STATE        = 1;
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Constructor
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    ModelInterpreter (InputStream in, OutputStream out)
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.in = in;
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.out = out;
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        init();
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    ModelInterpreter (InetSocketAddress sa) throws java.io.IOException
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ss = new ServerSocket();
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ss.setReuseAddress(true);
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ss.bind(sa);
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        init();
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    init()
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        new Thread(this, "ModelInterpreter").start();
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mHandlerThread = new HandlerThread("ModelInterpreter");
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mHandlerThread.start();
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Looper looper = mHandlerThread.getLooper();
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        simulatedCallState = new SimulatedGsmCallState(looper);
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Runnable Implementation
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void run()
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (;;) {
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (ss != null) {
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Socket s;
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                try {
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    s = ss.accept();
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } catch (java.io.IOException ex) {
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    Log.w(LOG_TAG,
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        "IOException on socket.accept(); stopping", ex);
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    return;
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                try {
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    in = s.getInputStream();
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    out = s.getOutputStream();
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } catch (java.io.IOException ex) {
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    Log.w(LOG_TAG,
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        "IOException on accepted socket(); re-listening", ex);
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    continue;
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Log.i(LOG_TAG, "New connection accepted");
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            lineReader = new LineReader (in);
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println ("Welcome");
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (;;) {
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                String line;
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                line = lineReader.getNextLine();
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //System.out.println("MI<< " + line);
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (line == null) {
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                synchronized(pausedResponseMonitor) {
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    while (pausedResponseCount > 0) {
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        try {
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            pausedResponseMonitor.wait();
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } catch (InterruptedException ex) {
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                synchronized (this) {
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    try {
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        finalResponse = "OK";
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        processLine(line);
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        println(finalResponse);
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } catch (InterpreterEx ex) {
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        println(ex.result);
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } catch (RuntimeException ex) {
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        ex.printStackTrace();
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        println("ERROR");
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.i(LOG_TAG, "Disconnected");
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (ss == null) {
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // no reconnect in this case
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Instance Methods
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Start the simulated phone ringing */
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerRing(String number)
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (this) {
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean success;
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            success = simulatedCallState.triggerRing(number);
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (success) {
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                println ("RING");
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** If a call is DIALING or ALERTING, progress it to the next state */
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    progressConnectingCallState()
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        simulatedCallState.progressConnectingCallState();
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    progressConnectingToActive()
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        simulatedCallState.progressConnectingToActive();
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** automatically progress mobile originated calls to ACTIVE.
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  default to true
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    setAutoProgressConnectingCall(boolean b)
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        simulatedCallState.setAutoProgressConnectingCall(b);
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    setNextDialFailImmediately(boolean b)
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        simulatedCallState.setNextDialFailImmediately(b);
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void setNextCallFailCause(int gsmCause)
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //FIXME implement
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** hangup ringing, dialing, or actuve calls */
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerHangupForeground()
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.triggerHangupForeground();
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (success) {
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println ("NO CARRIER");
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** hangup holding calls */
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerHangupBackground()
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.triggerHangupBackground();
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (success) {
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println ("NO CARRIER");
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** hangup all */
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerHangupAll()
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.triggerHangupAll();
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (success) {
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println ("NO CARRIER");
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    sendUnsolicited (String unsol)
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (this) {
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println(unsol);
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void triggerSsn(int a, int b) {}
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void triggerIncomingUssd(String statusCode, String message) {}
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerIncomingSMS(String message)
3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**************
3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        StringBuilder pdu = new StringBuilder();
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append ("00");      //SMSC address - 0 bytes
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append ("04");      // Message type indicator
3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // source address: +18005551212
3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append("918100551521F0");
3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // protocol ID and data coding scheme
3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append("0000");
3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Calendar c = Calendar.getInstance();
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append (c.
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (this) {
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println("+CMT: ,1\r" + pdu.toString());
4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville**************/
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    pauseResponses()
4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(pausedResponseMonitor) {
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pausedResponseCount++;
4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    resumeResponses()
4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(pausedResponseMonitor) {
4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pausedResponseCount--;
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (pausedResponseCount == 0) {
4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pausedResponseMonitor.notifyAll();
4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Private Instance Methods
4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onAnswer() throws InterpreterEx
4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.onAnswer();
4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onHangup() throws InterpreterEx
4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success = false;
4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.onAnswer();
4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        finalResponse = "NO CARRIER";
4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onCHLD(String command) throws InterpreterEx
4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // command starts with "+CHLD="
4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        char c0;
4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        char c1 = 0;
4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        c0 = command.charAt(6);
4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (command.length() >= 8) {
4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c1 = command.charAt(7);
4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.onChld(c0, c1);
4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    releaseHeldOrUDUB() throws InterpreterEx
4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.releaseHeldOrUDUB();
4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    releaseActiveAcceptHeldOrWaiting() throws InterpreterEx
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.releaseActiveAcceptHeldOrWaiting();
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    switchActiveAndHeldOrWaiting() throws InterpreterEx
5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.switchActiveAndHeldOrWaiting();
5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    separateCall(int index) throws InterpreterEx
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.separateCall(index);
5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    conference() throws InterpreterEx
5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.conference();
5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onDial(String command) throws InterpreterEx
5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        success = simulatedCallState.onDial(command.substring(1));
5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onCLCC() throws InterpreterEx
5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        List<String> lines;
5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        lines = simulatedCallState.getClccLines();
5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0, s = lines.size() ; i < s ; i++) {
5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println (lines.get(i));
5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onSMSSend(String command) throws InterpreterEx
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String pdu;
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        print ("> ");
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu = lineReader.getNextLineCtrlZ();
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        println("+CMGS: 1");
5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    processLine (String line) throws InterpreterEx
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String[] commands;
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        commands = splitCommands(line);
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0; i < commands.length ; i++) {
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String command = commands[i];
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (command.equals("A")) {
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onAnswer();
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.equals("H")) {
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onHangup();
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.startsWith("+CHLD=")) {
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onCHLD(command);
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.equals("+CLCC")) {
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onCLCC();
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.startsWith("D")) {
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onDial(command);
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.startsWith("+CMGS=")) {
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onSMSSend(command);
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                boolean found = false;
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                for (int j = 0; j < sDefaultResponses.length ; j++) {
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (command.equals(sDefaultResponses[j][0])) {
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        String r = sDefaultResponses[j][1];
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (r != null) {
5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            println(r);
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        found = true;
6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!found) {
6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    throw new InterpreterEx ("ERROR");
6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String[]
6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    splitCommands(String line) throws InterpreterEx
6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!line.startsWith ("AT")) {
6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (line.length() == 2) {
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Just AT by itself
6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return new String[0];
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String ret[] = new String[1];
6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //TODO fix case here too
6290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ret[0] = line.substring(2);
6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ret;
6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/****
6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // i = 2 to skip over AT
6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 2, s = line.length() ; i < s ; i++) {
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // r"|([A-RT-Z]\d?)" # Normal commands eg ATA or I0
6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // r"|(&[A-Z]\d*)" # & commands eg &C
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // r"|(S\d+(=\d+)?)" # S registers
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // r"((\+|%)\w+(\?|=([^;]+(;|$)))?)" # extended command eg +CREG=2
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (StringIndexOutOfBoundsException ex) {
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx ("ERROR");
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville***/
6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    println (String s)
6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(this) {
6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                byte[] bytes =  s.getBytes("US-ASCII");
6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //System.out.println("MI>> " + s);
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                out.write(bytes);
6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                out.write('\r');
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (IOException ex) {
6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ex.printStackTrace();
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    print (String s)
6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(this) {
6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                byte[] bytes =  s.getBytes("US-ASCII");
6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //System.out.println("MI>> " + s + " (no <cr>)");
6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                out.write(bytes);
6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (IOException ex) {
6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ex.printStackTrace();
6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    shutdown()
6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Looper looper = mHandlerThread.getLooper();
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (looper != null) {
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            looper.quit();
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            in.close();
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IOException ex) {
6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            out.close();
6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IOException ex) {
6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final String [][] sDefaultResponses = {
7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"E0Q0V1",   null},
7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CMEE=2",  null},
7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CREG=2",  null},
7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGREG=2", null},
7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CCWA=1",  null},
7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+COPS=0",  null},
7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CFUN=1",  null},
7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGMI",    "+CGMI: Android Model AT Interpreter\r"},
7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGMM",    "+CGMM: Android Model AT Interpreter\r"},
7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGMR",    "+CGMR: 1.0\r"},
7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGSN",    "000000000000000\r"},
7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CIMI",    "320720000000000\r"},
7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CSCS=?",  "+CSCS: (\"HEX\",\"UCS2\")\r"},
7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CFUN?",   "+CFUN: 1\r"},
7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "+COPS: 0,0,\"Android\"\r"
7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                + "+COPS: 0,1,\"Android\"\r"
7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                + "+COPS: 0,2,\"310995\"\r"},
7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CREG?",   "+CREG: 2,5, \"0113\", \"6614\"\r"},
7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGREG?",  "+CGREG: 2,0\r"},
7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CSQ",     "+CSQ: 16,99\r"},
7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CNMI?",   "+CNMI: 1,2,2,1,1\r"},
7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CLIR?",   "+CLIR: 1,3\r"},
7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"%CPVWI=2", "%CPVWI: 0\r"},
7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CUSD=1,\"#646#\"",  "+CUSD=0,\"You have used 23 minutes\"\r"},
7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=176,12258,0,0,10", "+CRSM: 144,0,981062200050259429F6\r"},
7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=192,12258,0,0,15", "+CRSM: 144,0,0000000A2FE204000FF55501020000\r"},
7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /* EF[ADN] */
7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=192,28474,0,0,15", "+CRSM: 144,0,0000005a6f3a040011f5220102011e\r"},
7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28474,1,4,30", "+CRSM: 144,0,437573746f6d65722043617265ffffff07818100398799f7ffffffffffff\r"},
7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28474,2,4,30", "+CRSM: 144,0,566f696365204d61696cffffffffffff07918150367742f3ffffffffffff\r"},
7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28474,3,4,30", "+CRSM: 144,0,4164676a6dffffffffffffffffffffff0b918188551512c221436587ff01\r"},
7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28474,4,4,30", "+CRSM: 144,0,810101c1ffffffffffffffffffffffff068114455245f8ffffffffffffff\r"},
7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /* EF[EXT1] */
7380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=192,28490,0,0,15", "+CRSM: 144,0,000000416f4a040011f5550102010d\r"},
7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28490,1,4,13", "+CRSM: 144,0,0206092143658709ffffffffff\r"}
7400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
742