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;
2199c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Savilleimport android.telephony.Rlog;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.IOException;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.InputStream;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.OutputStream;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.UnsupportedEncodingException;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.net.InetSocketAddress;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.net.ServerSocket;
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.net.Socket;
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List;
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville// Also in ATChannel.java
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleclass LineReader
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Not threadsafe
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Assumes input is ASCII
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Constants
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // For what it's worth, this is also the size of an
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // OMAP CSMI mailbox
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int BUFFER_SIZE = 0x1000;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // just to prevent constant allocations
4722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    byte mBuffer[] = new byte[BUFFER_SIZE];
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Instance Variables
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    InputStream mInStream;
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    LineReader (InputStream s)
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mInStream = s;
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    getNextLine()
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return getNextLine(false);
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    getNextLineCtrlZ()
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return getNextLine(true);
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: doesn't return the last incomplete line read on EOF, since
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * it doesn't typically matter anyway
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns NULL on EOF
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    getNextLine(boolean ctrlZ)
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int i = 0;
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (;;) {
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int result;
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                result = mInStream.read();
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (result < 0) {
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    return null;
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ctrlZ && result == 0x1a) {
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (result == '\r' || result == '\n') {
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (i == 0) {
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Skip leading cr/lf
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        continue;
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mBuffer[i++] = (byte)result;
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IOException ex) {
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IndexOutOfBoundsException ex) {
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            System.err.println("ATChannel: buffer overflow");
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
11222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            return new String(mBuffer, 0, i, "US-ASCII");
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (UnsupportedEncodingException ex) {
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            System.err.println("ATChannel: implausable UnsupportedEncodingException");
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return null;
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleclass InterpreterEx extends Exception
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    InterpreterEx (String result)
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
12722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mResult = result;
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mResult;
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class ModelInterpreter
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            implements Runnable, SimulatedRadioControl
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MAX_CALLS = 6;
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** number of msec between dialing -> alerting and alerting->active */
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int CONNECTING_PAUSE_MSEC = 5 * 100;
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final String LOG_TAG = "ModelInterpreter";
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Instance Variables
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    InputStream mIn;
14622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    OutputStream mOut;
14722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    LineReader mLineReader;
14822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    ServerSocket mSS;
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private String mFinalResponse;
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    SimulatedGsmCallState mSimulatedCallState;
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    HandlerThread mHandlerThread;
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    int mPausedResponseCount;
15722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    Object mPausedResponseMonitor = new Object();
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Events
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int PROGRESS_CALL_STATE        = 1;
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Constructor
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    ModelInterpreter (InputStream in, OutputStream out)
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
16822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mIn = in;
16922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mOut = out;
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        init();
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    ModelInterpreter (InetSocketAddress sa) throws java.io.IOException
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
17722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mSS = new ServerSocket();
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
17922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mSS.setReuseAddress(true);
18022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mSS.bind(sa);
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        init();
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    init()
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        new Thread(this, "ModelInterpreter").start();
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mHandlerThread = new HandlerThread("ModelInterpreter");
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mHandlerThread.start();
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Looper looper = mHandlerThread.getLooper();
19222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mSimulatedCallState = new SimulatedGsmCallState(looper);
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Runnable Implementation
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
197cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void run()
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (;;) {
20122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSS != null) {
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Socket s;
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                try {
20522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    s = mSS.accept();
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } catch (java.io.IOException ex) {
20799c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville                    Rlog.w(LOG_TAG,
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        "IOException on socket.accept(); stopping", ex);
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    return;
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                try {
21322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mIn = s.getInputStream();
21422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mOut = s.getOutputStream();
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } catch (java.io.IOException ex) {
21699c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville                    Rlog.w(LOG_TAG,
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        "IOException on accepted socket(); re-listening", ex);
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    continue;
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
22199c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville                Rlog.i(LOG_TAG, "New connection accepted");
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
22522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mLineReader = new LineReader (mIn);
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println ("Welcome");
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (;;) {
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                String line;
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
23222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                line = mLineReader.getNextLine();
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //System.out.println("MI<< " + line);
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (line == null) {
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
24022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                synchronized(mPausedResponseMonitor) {
24122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    while (mPausedResponseCount > 0) {
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        try {
24322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mPausedResponseMonitor.wait();
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } catch (InterruptedException ex) {
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                synchronized (this) {
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    try {
25122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        mFinalResponse = "OK";
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        processLine(line);
25322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        println(mFinalResponse);
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } catch (InterpreterEx ex) {
25522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        println(ex.mResult);
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } catch (RuntimeException ex) {
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        ex.printStackTrace();
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        println("ERROR");
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
26399c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville            Rlog.i(LOG_TAG, "Disconnected");
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
26522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSS == 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 */
276cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerRing(String number)
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (this) {
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean success;
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
28322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            success = mSimulatedCallState.triggerRing(number);
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (success) {
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                println ("RING");
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** If a call is DIALING or ALERTING, progress it to the next state */
292cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    progressConnectingCallState()
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
29622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mSimulatedCallState.progressConnectingCallState();
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */
301cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    progressConnectingToActive()
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
30522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mSimulatedCallState.progressConnectingToActive();
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** automatically progress mobile originated calls to ACTIVE.
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  default to true
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
311cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    setAutoProgressConnectingCall(boolean b)
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
31522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mSimulatedCallState.setAutoProgressConnectingCall(b);
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
318cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    setNextDialFailImmediately(boolean b)
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
32222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mSimulatedCallState.setNextDialFailImmediately(b);
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
325cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void setNextCallFailCause(int gsmCause)
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //FIXME implement
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** hangup ringing, dialing, or actuve calls */
333cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerHangupForeground()
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
33922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        success = mSimulatedCallState.triggerHangupForeground();
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (success) {
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println ("NO CARRIER");
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** hangup holding calls */
347cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerHangupBackground()
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
35322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        success = mSimulatedCallState.triggerHangupBackground();
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (success) {
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println ("NO CARRIER");
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** hangup all */
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
362cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerHangupAll()
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
36822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        success = mSimulatedCallState.triggerHangupAll();
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (success) {
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println ("NO CARRIER");
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    sendUnsolicited (String unsol)
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (this) {
3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println(unsol);
3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
383cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void triggerSsn(int a, int b) {}
385cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void triggerIncomingUssd(String statusCode, String message) {}
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
388cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    triggerIncomingSMS(String message)
3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**************
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        StringBuilder pdu = new StringBuilder();
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append ("00");      //SMSC address - 0 bytes
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append ("04");      // Message type indicator
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // source address: +18005551212
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append("918100551521F0");
4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // protocol ID and data coding scheme
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append("0000");
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Calendar c = Calendar.getInstance();
4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pdu.append (c.
4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (this) {
4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println("+CMT: ,1\r" + pdu.toString());
4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville**************/
4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
418cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    pauseResponses()
4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
42222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        synchronized(mPausedResponseMonitor) {
42322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPausedResponseCount++;
4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
427cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    resumeResponses()
4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
43122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        synchronized(mPausedResponseMonitor) {
43222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPausedResponseCount--;
4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
43422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mPausedResponseCount == 0) {
43522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPausedResponseMonitor.notifyAll();
4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Private Instance Methods
4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onAnswer() throws InterpreterEx
4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
44722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        success = mSimulatedCallState.onAnswer();
4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onHangup() throws InterpreterEx
4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success = false;
4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
45922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        success = mSimulatedCallState.onAnswer();
4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
46522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mFinalResponse = "NO CARRIER";
4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onCHLD(String command) throws InterpreterEx
4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // command starts with "+CHLD="
4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        char c0;
4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        char c1 = 0;
4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        c0 = command.charAt(6);
4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (command.length() >= 8) {
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c1 = command.charAt(7);
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
48222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        success = mSimulatedCallState.onChld(c0, c1);
4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    onDial(String command) throws InterpreterEx
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean success;
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
49422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        success = mSimulatedCallState.onDial(command.substring(1));
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!success) {
4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
502cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    onCLCC()
5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        List<String> lines;
5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
50622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        lines = mSimulatedCallState.getClccLines();
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0, s = lines.size() ; i < s ; i++) {
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            println (lines.get(i));
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
514cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    onSMSSend(String command)
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String pdu;
5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        print ("> ");
51922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        pdu = mLineReader.getNextLineCtrlZ();
5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        println("+CMGS: 1");
5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    processLine (String line) throws InterpreterEx
5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String[] commands;
5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        commands = splitCommands(line);
5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0; i < commands.length ; i++) {
5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String command = commands[i];
5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (command.equals("A")) {
5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onAnswer();
5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.equals("H")) {
5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onHangup();
5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.startsWith("+CHLD=")) {
5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onCHLD(command);
5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.equals("+CLCC")) {
5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onCLCC();
5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.startsWith("D")) {
5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onDial(command);
5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (command.startsWith("+CMGS=")) {
5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onSMSSend(command);
5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                boolean found = false;
5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                for (int j = 0; j < sDefaultResponses.length ; j++) {
5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (command.equals(sDefaultResponses[j][0])) {
5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        String r = sDefaultResponses[j][1];
5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (r != null) {
5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            println(r);
5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        found = true;
5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!found) {
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    throw new InterpreterEx ("ERROR");
5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String[]
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    splitCommands(String line) throws InterpreterEx
5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!line.startsWith ("AT")) {
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx("ERROR");
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (line.length() == 2) {
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Just AT by itself
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return new String[0];
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String ret[] = new String[1];
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //TODO fix case here too
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ret[0] = line.substring(2);
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ret;
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/****
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // i = 2 to skip over AT
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 2, s = line.length() ; i < s ; i++) {
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // r"|([A-RT-Z]\d?)" # Normal commands eg ATA or I0
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // r"|(&[A-Z]\d*)" # & commands eg &C
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // r"|(S\d+(=\d+)?)" # S registers
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // r"((\+|%)\w+(\?|=([^;]+(;|$)))?)" # extended command eg +CREG=2
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (StringIndexOutOfBoundsException ex) {
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new InterpreterEx ("ERROR");
5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville***/
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    println (String s)
6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(this) {
6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                byte[] bytes =  s.getBytes("US-ASCII");
6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //System.out.println("MI>> " + s);
6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
61222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mOut.write(bytes);
61322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mOut.write('\r');
6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (IOException ex) {
6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ex.printStackTrace();
6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    print (String s)
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(this) {
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                byte[] bytes =  s.getBytes("US-ASCII");
6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //System.out.println("MI>> " + s + " (no <cr>)");
6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
62922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mOut.write(bytes);
6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (IOException ex) {
6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ex.printStackTrace();
6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
637cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    shutdown()
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Looper looper = mHandlerThread.getLooper();
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (looper != null) {
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            looper.quit();
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
64722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mIn.close();
6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IOException ex) {
6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
65122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mOut.close();
6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (IOException ex) {
6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final String [][] sDefaultResponses = {
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"E0Q0V1",   null},
6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CMEE=2",  null},
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CREG=2",  null},
6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGREG=2", null},
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CCWA=1",  null},
6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+COPS=0",  null},
6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CFUN=1",  null},
6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGMI",    "+CGMI: Android Model AT Interpreter\r"},
6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGMM",    "+CGMM: Android Model AT Interpreter\r"},
6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGMR",    "+CGMR: 1.0\r"},
6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGSN",    "000000000000000\r"},
6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CIMI",    "320720000000000\r"},
6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CSCS=?",  "+CSCS: (\"HEX\",\"UCS2\")\r"},
6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CFUN?",   "+CFUN: 1\r"},
6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "+COPS: 0,0,\"Android\"\r"
6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                + "+COPS: 0,1,\"Android\"\r"
6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                + "+COPS: 0,2,\"310995\"\r"},
6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CREG?",   "+CREG: 2,5, \"0113\", \"6614\"\r"},
6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CGREG?",  "+CGREG: 2,0\r"},
6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CSQ",     "+CSQ: 16,99\r"},
6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CNMI?",   "+CNMI: 1,2,2,1,1\r"},
6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CLIR?",   "+CLIR: 1,3\r"},
6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"%CPVWI=2", "%CPVWI: 0\r"},
6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CUSD=1,\"#646#\"",  "+CUSD=0,\"You have used 23 minutes\"\r"},
6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=176,12258,0,0,10", "+CRSM: 144,0,981062200050259429F6\r"},
6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=192,12258,0,0,15", "+CRSM: 144,0,0000000A2FE204000FF55501020000\r"},
6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /* EF[ADN] */
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=192,28474,0,0,15", "+CRSM: 144,0,0000005a6f3a040011f5220102011e\r"},
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28474,1,4,30", "+CRSM: 144,0,437573746f6d65722043617265ffffff07818100398799f7ffffffffffff\r"},
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28474,2,4,30", "+CRSM: 144,0,566f696365204d61696cffffffffffff07918150367742f3ffffffffffff\r"},
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28474,3,4,30", "+CRSM: 144,0,4164676a6dffffffffffffffffffffff0b918188551512c221436587ff01\r"},
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28474,4,4,30", "+CRSM: 144,0,810101c1ffffffffffffffffffffffff068114455245f8ffffffffffffff\r"},
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /* EF[EXT1] */
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=192,28490,0,0,15", "+CRSM: 144,0,000000416f4a040011f5550102010d\r"},
6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {"+CRSM=178,28490,1,4,13", "+CRSM: 144,0,0206092143658709ffffffffff\r"}
6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
697