Bump java lib versions to 13
[fw/altos] / altosdroid / src / org / altusmetrum / AltosDroid / AltosBluetooth.java
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  * Copyright © 2012 Mike Beattie <mike@ethernal.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18  */
19
20 package org.altusmetrum.AltosDroid;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.util.UUID;
26
27 import android.bluetooth.BluetoothAdapter;
28 import android.bluetooth.BluetoothDevice;
29 import android.bluetooth.BluetoothSocket;
30 //import android.os.Bundle;
31 import android.os.Handler;
32 //import android.os.Message;
33
34 import org.altusmetrum.altoslib_13.*;
35
36 public class AltosBluetooth extends AltosDroidLink {
37
38         private ConnectThread    connect_thread = null;
39
40         private BluetoothDevice  device;
41         private BluetoothSocket  socket;
42         private InputStream      input;
43         private OutputStream     output;
44         private boolean          pause;
45
46         // Constructor
47         public AltosBluetooth(BluetoothDevice device, Handler handler, boolean pause) {
48                 super(handler);
49                 this.device = device;
50                 this.handler = handler;
51                 this.pause = pause;
52
53                 connect_thread = new ConnectThread();
54                 connect_thread.start();
55         }
56
57         void connected() {
58                 if (closed()) {
59                         AltosDebug.debug("connected after closed");
60                         return;
61                 }
62
63                 AltosDebug.check_ui("connected\n");
64                 try {
65                         synchronized(this) {
66                                 if (socket != null) {
67                                         input = socket.getInputStream();
68                                         output = socket.getOutputStream();
69                                         super.connected();
70                                 }
71                         }
72                 } catch (InterruptedException ie) {
73                         connect_failed();
74                 } catch (IOException io) {
75                         connect_failed();
76                 }
77         }
78
79         private void connect_failed() {
80                 if (closed()) {
81                         AltosDebug.debug("connect_failed after closed");
82                         return;
83                 }
84
85                 close_device();
86                 input = null;
87                 output = null;
88                 handler.obtainMessage(TelemetryService.MSG_CONNECT_FAILED, this).sendToTarget();
89                 AltosDebug.error("ConnectThread: Failed to establish connection");
90         }
91
92         void close_device() {
93                 BluetoothSocket tmp_socket;
94
95                 synchronized(this) {
96                         tmp_socket = socket;
97                         socket = null;
98                 }
99
100                 if (tmp_socket != null) {
101                         try {
102                                 tmp_socket.close();
103                         } catch (IOException e) {
104                                 AltosDebug.error("close_socket failed");
105                         }
106                 }
107         }
108
109         public void close() {
110                 super.close();
111                 input = null;
112                 output = null;
113         }
114
115         private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
116
117         private void create_socket(BluetoothDevice  device) {
118
119                 BluetoothSocket tmp_socket = null;
120
121                 AltosDebug.check_ui("create_socket\n");
122                 try {
123                         tmp_socket = device.createInsecureRfcommSocketToServiceRecord(SPP_UUID);
124                 } catch (IOException e) {
125                         e.printStackTrace();
126                 }
127                 if (socket != null) {
128                         AltosDebug.debug("Socket already allocated %s", socket.toString());
129                         close_device();
130                 }
131                 synchronized (this) {
132                         socket = tmp_socket;
133                 }
134         }
135
136         private class ConnectThread extends Thread {
137
138                 public void run() {
139                         AltosDebug.debug("ConnectThread: BEGIN (pause %b)", pause);
140                         setName("ConnectThread");
141
142                         if (pause) {
143                                 try {
144                                         Thread.sleep(4000);
145                                 } catch (InterruptedException e) {
146                                 }
147                         }
148
149                         create_socket(device);
150                         // Always cancel discovery because it will slow down a connection
151                         try {
152                                 BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
153                         } catch (Exception e) {
154                                 AltosDebug.debug("cancelDiscovery exception %s", e.toString());
155                         }
156
157                         BluetoothSocket local_socket = null;
158
159                         synchronized (AltosBluetooth.this) {
160                                 if (!closed())
161                                         local_socket = socket;
162                         }
163
164                         if (local_socket != null) {
165                                 try {
166                                         // Make a connection to the BluetoothSocket
167                                         // This is a blocking call and will only return on a
168                                         // successful connection or an exception
169                                         local_socket.connect();
170                                 } catch (Exception e) {
171                                         AltosDebug.debug("Connect exception %s", e.toString());
172                                         try {
173                                                 local_socket.close();
174                                         } catch (Exception ce) {
175                                                 AltosDebug.debug("Close exception %s", ce.toString());
176                                         }
177                                         local_socket = null;
178                                 }
179                         }
180
181                         if (local_socket != null) {
182                                 connected();
183                         } else {
184                                 connect_failed();
185                         }
186
187                         AltosDebug.debug("ConnectThread: completed");
188                 }
189         }
190
191         private synchronized void wait_connected() throws InterruptedException, IOException {
192                 AltosDebug.check_ui("wait_connected\n");
193                 if (input == null && socket != null) {
194                         AltosDebug.debug("wait_connected...");
195                         wait();
196                         AltosDebug.debug("wait_connected done");
197                 }
198                 if (socket == null)
199                         throw new IOException();
200         }
201
202         int write(byte[] buffer, int len) {
203                 if (output == null)
204                         return -1;
205                 try {
206                         output.write(buffer, 0, len);
207                 } catch (IOException ie) {
208                         return -1;
209                 }
210                 return len;
211         }
212
213         int read(byte[] buffer, int len) {
214                 if (input == null)
215                         return -1;
216                 try {
217                         return input.read(buffer, 0, len);
218                 } catch (IOException ie) {
219                         return -1;
220                 }
221         }
222
223         // Stubs of required methods when extending AltosLink
224         public boolean can_cancel_reply()   { return false; }
225         public boolean show_reply_timeout() { return true; }
226         public void hide_reply_timeout()    { }
227
228 }