1cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondepackage com.android.bluetooth.sap;
2cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
3cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.io.IOException;
4cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.io.InputStream;
5cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.io.OutputStream;
6cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
7cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport org.android.btsap.SapApi.MsgHeader;
8cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
9cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport com.google.protobuf.micro.CodedInputStreamMicro;
10cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport com.google.protobuf.micro.CodedOutputStreamMicro;
11cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
12cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.net.LocalSocket;
13cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.net.LocalSocketAddress;
14cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.Handler;
15cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.Message;
16cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.util.Log;
17cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
18cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondepublic class SapRilReceiver implements Runnable {
19cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
20cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    private static final String TAG = "SapRilReceiver";
21cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    public static final boolean DEBUG = true;
22cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    public static final boolean VERBOSE = true;
23cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
24cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    private static final String SOCKET_NAME_RIL_BT = "sap_uim_socket1";
25cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    // match with constant in ril.cpp - as in RIL.java
26cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    private static final int SOCKET_OPEN_RETRY_MILLIS = 4 * 1000;
27cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
28cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    LocalSocket mSocket = null;
29cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    CodedOutputStreamMicro mRilBtOutStream = null;
30cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    InputStream mRilBtInStream = null;
31cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    private Handler mSapServerMsgHandler = null;
32bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde    private Handler mSapServiceHandler = null;
33cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
34cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    public static final int RIL_MAX_COMMAND_BYTES = (8 * 1024);
35cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    byte[] buffer = new byte[RIL_MAX_COMMAND_BYTES];
36cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
37bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde    public SapRilReceiver(Handler SapServerMsgHandler, Handler sapServiceHandler) {
38cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        mSapServerMsgHandler = SapServerMsgHandler;
39bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde        mSapServiceHandler = sapServiceHandler;
40cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
41cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
42cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    /**
43cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * Open the RIL-BT socket in rild. Will continuously try to open the BT socket until
44cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * success. (Based on the approach used to open the rild socket in telephony)
45cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * @return The socket handle
46cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     */
47cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    public static LocalSocket openRilBtSocket() {
48cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        int retryCount = 0;
49cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        LocalSocket rilSocket = null;
50cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
51cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        for (;;) {
52cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            LocalSocketAddress address;
53cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
54cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            try {
55cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                rilSocket = new LocalSocket();
56cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                address = new LocalSocketAddress(SOCKET_NAME_RIL_BT,
57cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        LocalSocketAddress.Namespace.RESERVED);
58cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                rilSocket.connect(address);
59cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                break; // Socket opened
60cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            } catch (IOException ex){
61cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                try {
62cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                    if (rilSocket != null) {
63cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        rilSocket.close();
64cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                    }
65cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                } catch (IOException ex2) {
66cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                    //ignore failure to close after failure to connect
67cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                }
68cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
69cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                // don't print an error message after the the first time
70cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                // or after the 8th time
71cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                if (retryCount == 8) {
72cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                    Log.e (TAG,
73cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        "Couldn't find '" + SOCKET_NAME_RIL_BT
74cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        + "' socket after " + retryCount
75cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        + " times, continuing to retry silently");
76cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                } else if (retryCount > 0 && retryCount < 8) {
77cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                    Log.i (TAG,
78cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        "Couldn't find '" + SOCKET_NAME_RIL_BT
79cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        + "' socket; retrying after timeout");
80bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                    if (VERBOSE) Log.w(TAG, ex);
81cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                }
82cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
83cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                try {
84cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                    Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
85cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                } catch (InterruptedException er) {
86cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                }
87cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
88cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                retryCount++;
89cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                continue;
90cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            }
91cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        }
92cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        return rilSocket;
93cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
94cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
95cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
96cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    public CodedOutputStreamMicro getRilBtOutStream() {
97cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        return mRilBtOutStream;
98cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
99cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
100a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    /**
101a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     * Notify SapServer that this class is ready for shutdown.
102a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     */
103a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    private void notifyShutdown() {
104a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        if (DEBUG) Log.i(TAG, "notifyShutdown()");
105a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        // If we are already shutdown, don't bother sending a notification.
106a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        synchronized (this) {
107a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde            if (mSocket != null) sendShutdownMessage();
108a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        }
109cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
110cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
111cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    /**
112cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * This will terminate the SapRilReceiver thread, by closing the RIL-BT in-/output
113cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * streams.
114cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     */
115cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    public void shutdown() {
116bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde        if (DEBUG) Log.i(TAG, "shutdown()");
117cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
118cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        /* On Android you need to close the IOstreams using Socket.shutdown*
119cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde         * The IOstream close must not be used, as it some how decouples the
120cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde         * stream from the socket, and when the socket is closed, the pending
121cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde         * reads never return nor throw and exception.
122cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde         * Hence here we use the shutdown method: */
123a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        synchronized (this) {
124a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde            if (mSocket != null) {
125a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                try {
126a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                    mSocket.shutdownOutput();
127a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                } catch (IOException e) {}
128a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                try {
129a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                    mSocket.shutdownInput();
130a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                } catch (IOException e) {}
131a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                try {
132a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                    mSocket.close();
133a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                } catch (IOException ex) {
134a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                    if (VERBOSE) Log.e(TAG,"Uncaught exception", ex);
135a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                } finally {
136a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                    mSocket = null;
137a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                }
138cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            }
139cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        }
140cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
141cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
142cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    /**
143cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * Read the message into buffer
144cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * @param is
145cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * @param buffer
146cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * @return the length of the message
147cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * @throws IOException
148cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     */
149cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    private static int readMessage(InputStream is, byte[] buffer) throws IOException {
150cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        int countRead;
151cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        int offset;
152cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        int remaining;
153cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        int messageLength;
154cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
155cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        // Read in the length of the message
156cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        offset = 0;
157cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        remaining = 4;
158cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        do {
159cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            countRead = is.read(buffer, offset, remaining);
160cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
161cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            if (countRead < 0 ) {
162cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                Log.e(TAG, "Hit EOS reading message length");
163cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                return -1;
164cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            }
165cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
166cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            offset += countRead;
167cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            remaining -= countRead;
168cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        } while (remaining > 0);
169cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
170cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        messageLength = ((buffer[0] & 0xff) << 24)
171cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                | ((buffer[1] & 0xff) << 16)
172cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                | ((buffer[2] & 0xff) << 8)
173cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                | (buffer[3] & 0xff);
174bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde        if (VERBOSE) Log.e(TAG,"Message length found to be: "+messageLength);
175cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        // Read the message
176cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        offset = 0;
177cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        remaining = messageLength;
178cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        do {
179cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            countRead = is.read(buffer, offset, remaining);
180cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
181cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            if (countRead < 0 ) {
182cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                Log.e(TAG, "Hit EOS reading message.  messageLength=" + messageLength
183cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        + " remaining=" + remaining);
184cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                return -1;
185cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            }
186cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
187cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            offset += countRead;
188cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            remaining -= countRead;
189cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        } while (remaining > 0);
190cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
191cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        return messageLength;
192cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
193cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
194cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    /**
195cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * The RIL reader thread. Will handle open of the RIL-BT socket, and notify
196cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * SapServer when done.
197cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     */
198cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    @Override
199cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    public void run() {
200cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
201cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        try {
202bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde            if (VERBOSE) Log.i(TAG, "Starting RilBtReceiverThread...");
203cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
204cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            mSocket = openRilBtSocket();
205cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            mRilBtInStream = mSocket.getInputStream();
206cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            mRilBtOutStream = CodedOutputStreamMicro.newInstance(mSocket.getOutputStream());
207cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
208cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            // Notify the SapServer that we have connected to the RilBtSocket
209a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde            sendRilConnectMessage();
210cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
211cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            // The main loop - read messages and forward to SAP server
212cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            for (;;) {
213cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                SapMessage sapMsg = null;
214cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                MsgHeader rilMsg;
215cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
216bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                if (VERBOSE) Log.i(TAG, "Waiting for incoming message...");
217bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                int length = readMessage(mRilBtInStream, buffer);
218bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde
219bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                SapService.notifyUpdateWakeLock(mSapServiceHandler);
220bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde
221a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                if (length == -1) {
222a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                    if (DEBUG) Log.i(TAG, "EOF reached - closing down.");
223a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                    break;
224a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde                }
225a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde
226bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                CodedInputStreamMicro msgStream =
227bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                        CodedInputStreamMicro.newInstance(buffer, 0, length);
228cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
229cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                rilMsg = MsgHeader.parseFrom(msgStream);
230cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
231bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                if (VERBOSE) Log.i(TAG, "Message received.");
232cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
233cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                sapMsg = SapMessage.newInstance(rilMsg);
234cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
235bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                if (sapMsg != null && sapMsg.getMsgType() != SapMessage.INVALID_VALUE)
236cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                {
237bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde                    if (sapMsg.getMsgType() < SapMessage.ID_RIL_BASE) {
238cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        sendClientMessage(sapMsg);
239cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                    } else {
240cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                        sendRilIndMessage(sapMsg);
241cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                    }
242cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde                } // else simply ignore it
243cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            }
244a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde
245cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        } catch (IOException e) {
246a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde            notifyShutdown(); /* Only needed in case of a connection error */
247cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            Log.i(TAG, "'" + SOCKET_NAME_RIL_BT + "' socket inputStream closed", e);
248a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde
249a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        } finally {
250cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde            Log.i(TAG, "Disconnected from '" + SOCKET_NAME_RIL_BT + "' socket");
251cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        }
252cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
253cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
254cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    /**
255a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     * Notify SapServer that the RIL socket is connected
256a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     */
257a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    private void sendRilConnectMessage() {
258a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        if (mSapServerMsgHandler != null) {
259a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde            mSapServerMsgHandler.sendEmptyMessage(SapServer.SAP_MSG_RIL_CONNECT);
260a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        }
261a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    }
262a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde
263a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    /**
264a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     * Send reply (solicited) message from the RIL to the Sap Server Handler Thread
265cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     * @param sapMsg The message to send
266cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde     */
267cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    private void sendClientMessage(SapMessage sapMsg) {
268cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        Message newMsg = mSapServerMsgHandler.obtainMessage(SapServer.SAP_MSG_RFC_REPLY, sapMsg);
269cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        mSapServerMsgHandler.sendMessage(newMsg);
270cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
271cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
272a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    /**
273a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     * Send a shutdown signal to SapServer to indicate the
274a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     */
275a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    private void sendShutdownMessage() {
276a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        if (mSapServerMsgHandler != null) {
277a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde            mSapServerMsgHandler.sendEmptyMessage(SapServer.SAP_RIL_SOCK_CLOSED);
278a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde        }
279a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    }
280a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde
281a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde    /**
282a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     * Send indication (unsolicited) message from RIL to the Sap Server Handler Thread
283a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     * @param sapMsg The message to send
284a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde     */
285cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    private void sendRilIndMessage(SapMessage sapMsg) {
286cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        Message newMsg = mSapServerMsgHandler.obtainMessage(SapServer.SAP_MSG_RIL_IND, sapMsg);
287cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde        mSapServerMsgHandler.sendMessage(newMsg);
288cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde    }
289cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde
290cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde}
291