BluetoothOppRfcommListener.java revision 09e9cba205af60b3f42e7a4d891a7d1392e1f2a5
1/* 2 * Copyright (c) 2008-2009, Motorola, Inc. 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * - Neither the name of the Motorola, Inc. nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33package com.android.bluetooth.opp; 34 35import java.io.IOException; 36import java.net.ServerSocket; 37import java.net.Socket; 38import java.net.SocketException; 39 40import android.bluetooth.BluetoothServerSocket; 41import android.bluetooth.BluetoothSocket; 42import android.os.Handler; 43import android.os.Message; 44import android.util.Log; 45 46/** 47 * This class listens on OPUSH channel for incoming 48 * connection 49 */ 50public class BluetoothOppRfcommListener { 51 private static final String TAG = "BtOpp RfcommListener"; 52 53 private volatile boolean mInterrupted; 54 55 private Thread mSocketAcceptThread; 56 57 private Handler mCallback; 58 59 private static final int ACCEPT_WAIT_TIMEOUT = 5000; 60 61 private static final int CREATE_RETRY_TIME = 10; 62 63 public static final int DEFAULT_OPP_CHANNEL = 12; 64 65 public static final int MSG_INCOMING_BTOPP_CONNECTION = 100; 66 67 private int mBtOppRfcommChannel = -1; 68 69 public BluetoothOppRfcommListener() { 70 this(DEFAULT_OPP_CHANNEL); 71 } 72 73 public BluetoothOppRfcommListener(int channel) { 74 mBtOppRfcommChannel = channel; 75 } 76 77 public synchronized boolean start(Handler callback) { 78 if (mSocketAcceptThread == null) { 79 mCallback = callback; 80 if (Constants.LOGV) { 81 Log.v(TAG, "create mSocketAcceptThread"); 82 } 83 mSocketAcceptThread = new Thread(TAG) { 84 85 public void run() { 86 if (Constants.LOGV) { 87 Log.v(TAG, "BluetoothOppRfcommListener thread starting"); 88 } 89 if (Constants.USE_TCP_DEBUG) { 90 ServerSocket mServerSocket = null; 91 try { 92 if (Constants.LOGVV) { 93 Log.v(TAG, "Create ServerSocket on port " 94 + Constants.TCP_DEBUG_PORT); 95 } 96 97 mServerSocket = new ServerSocket(Constants.TCP_DEBUG_PORT, 1); 98 99 } catch (IOException e) { 100 Log.e(TAG, "Error listing on port" + Constants.TCP_DEBUG_PORT); 101 mInterrupted = true; 102 } 103 while (!mInterrupted) { 104 try { 105 mServerSocket.setSoTimeout(ACCEPT_WAIT_TIMEOUT); 106 Socket clientSocket = mServerSocket.accept(); 107 108 if (clientSocket == null) { 109 if (Constants.LOGVV) { 110 Log.v(TAG, "incomming connection time out"); 111 } 112 } else { 113 if (Constants.LOGV) { 114 Log.v(TAG, "TCP Socket connected!"); 115 } 116 Log.d(TAG, "remote addr is " 117 + clientSocket.getRemoteSocketAddress()); 118 TestTcpTransport transport = new TestTcpTransport(clientSocket); 119 Message msg = Message.obtain(); 120 msg.setTarget(mCallback); 121 msg.what = MSG_INCOMING_BTOPP_CONNECTION; 122 msg.obj = transport; 123 msg.sendToTarget(); 124 } 125 } catch (SocketException e) { 126 Log.e(TAG, "Error accept connection " + e); 127 } catch (IOException e) { 128 Log.e(TAG, "Error accept connection " + e); 129 } 130 } 131 if (Constants.LOGV) { 132 Log.v(TAG, "TCP listen thread finished"); 133 } 134 try { 135 mServerSocket.close(); 136 } catch (IOException e) { 137 Log.e(TAG, "Error close mServerSocker " + e); 138 } 139 } else { 140 BluetoothServerSocket mServerSocket = null; 141 boolean serverOK = true; 142 143 /* 144 * it's possible that create will fail in some cases. 145 * retry for 10 times 146 */ 147 if (Constants.LOGVV) { 148 Log.v(TAG, "Create BluetoothServerSocket on channel " 149 + mBtOppRfcommChannel); 150 } 151 for (int i = 0; i < CREATE_RETRY_TIME && !mInterrupted; i++) { 152 try { 153 mServerSocket = BluetoothServerSocket 154 .listenUsingInsecureRfcommOn(mBtOppRfcommChannel); 155 } catch (IOException e1) { 156 Log.d(TAG, "Error create RfcommServerSocket " + e1); 157 serverOK = false; 158 } 159 if (!serverOK) { 160 synchronized (this) { 161 try { 162 if (Constants.LOGVV) { 163 Log.v(TAG, "wait 3 seconds"); 164 } 165 Thread.sleep(3000); 166 } catch (InterruptedException e) { 167 Log.e(TAG, "socketAcceptThread thread was interrupted (3)"); 168 mInterrupted = true; 169 } 170 } 171 } else { 172 break; 173 } 174 } 175 if (!serverOK) { 176 Log.e(TAG, "Error start listening after " + CREATE_RETRY_TIME + " try"); 177 mInterrupted = true; 178 } 179 180 BluetoothSocket clientSocket; 181 while (!mInterrupted) { 182 try { 183 clientSocket = mServerSocket.accept(ACCEPT_WAIT_TIMEOUT); 184 if (Constants.LOGVV) { 185 Log.v(TAG, "BluetoothSocket connected!"); 186 Log.v(TAG, "remote addr is " + clientSocket.getAddress()); 187 } 188 BluetoothOppRfcommTransport transport = new BluetoothOppRfcommTransport( 189 clientSocket); 190 Message msg = Message.obtain(); 191 msg.setTarget(mCallback); 192 msg.what = MSG_INCOMING_BTOPP_CONNECTION; 193 msg.obj = transport; 194 msg.sendToTarget(); 195 } catch (IOException e) { 196 if (Constants.LOGVV) { 197 Log.v(TAG, "Error accept connection " + e); 198 } 199 } 200 } 201 try { 202 if (mServerSocket != null) { 203 if (Constants.LOGVV) { 204 Log.v(TAG, "close mServerSocket"); 205 } 206 mServerSocket.close(); 207 //TODO 208 //mServerSocket.destroy(); 209 } 210 } catch (IOException e) { 211 Log.e(TAG, "Errro close mServerSocket " + e); 212 } 213 if (Constants.LOGV) { 214 Log.v(TAG, "BluetoothSocket listen thread finished"); 215 } 216 } 217 } 218 }; 219 mInterrupted = false; 220 mSocketAcceptThread.start(); 221 } 222 return true; 223 } 224 225 public synchronized void stop() { 226 if (mSocketAcceptThread != null) { 227 if (Constants.LOGV) { 228 Log.v(TAG, "stopping Connect Thread"); 229 } 230 mInterrupted = true; 231 try { 232 mSocketAcceptThread.interrupt(); 233 if (Constants.LOGVV) { 234 Log.v(TAG, "waiting for thread to terminate"); 235 } 236 mSocketAcceptThread.join(); 237 mSocketAcceptThread = null; 238 mCallback = null; 239 } catch (InterruptedException e) { 240 if (Constants.LOGVV) { 241 Log.v(TAG, "Interrupted waiting for Accept Thread to join"); 242 } 243 } 244 } 245 } 246} 247