BluetoothOppRfcommListener.java revision 888485a3f5fe991116c5536bb6d6903d47b63a70
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.BluetoothAdapter; 41import android.bluetooth.BluetoothServerSocket; 42import android.bluetooth.BluetoothSocket; 43import android.os.Handler; 44import android.os.Message; 45import android.util.Log; 46 47/** 48 * This class listens on OPUSH channel for incoming connection 49 */ 50public class BluetoothOppRfcommListener { 51 private static final String TAG = "BtOppRfcommListener"; 52 53 private static final boolean D = Constants.DEBUG; 54 55 private static final boolean V = Constants.VERBOSE; 56 57 public static final int MSG_INCOMING_BTOPP_CONNECTION = 100; 58 59 private volatile boolean mInterrupted; 60 61 private Thread mSocketAcceptThread; 62 63 private Handler mCallback; 64 65 private static final int CREATE_RETRY_TIME = 10; 66 67 private static final int DEFAULT_OPP_CHANNEL = 12; 68 69 private final int mBtOppRfcommChannel; 70 71 private final BluetoothAdapter mAdapter; 72 73 private BluetoothServerSocket mBtServerSocket = null; 74 75 private ServerSocket mTcpServerSocket = null; 76 77 public BluetoothOppRfcommListener(BluetoothAdapter adapter) { 78 this(adapter, DEFAULT_OPP_CHANNEL); 79 } 80 81 public BluetoothOppRfcommListener(BluetoothAdapter adapter, int channel) { 82 mBtOppRfcommChannel = channel; 83 mAdapter = adapter; 84 } 85 86 public synchronized boolean start(Handler callback) { 87 if (mSocketAcceptThread == null) { 88 mCallback = callback; 89 90 mSocketAcceptThread = new Thread(TAG) { 91 92 public void run() { 93 if (Constants.USE_TCP_DEBUG) { 94 try { 95 if (V) Log.v(TAG, "Create TCP ServerSocket"); 96 mTcpServerSocket = new ServerSocket(Constants.TCP_DEBUG_PORT, 1); 97 } catch (IOException e) { 98 Log.e(TAG, "Error listing on port" + Constants.TCP_DEBUG_PORT); 99 mInterrupted = true; 100 } 101 while (!mInterrupted) { 102 try { 103 Socket clientSocket = mTcpServerSocket.accept(); 104 105 if (V) Log.v(TAG, "Socket connected!"); 106 TestTcpTransport transport = new TestTcpTransport(clientSocket); 107 Message msg = Message.obtain(); 108 msg.setTarget(mCallback); 109 msg.what = MSG_INCOMING_BTOPP_CONNECTION; 110 msg.obj = transport; 111 msg.sendToTarget(); 112 113 } catch (IOException e) { 114 Log.e(TAG, "Error accept connection " + e); 115 } 116 } 117 if (V) Log.v(TAG, "TCP listen thread finished"); 118 } else { 119 boolean serverOK = true; 120 121 /* 122 * it's possible that create will fail in some cases. 123 * retry for 10 times 124 */ 125 for (int i = 0; i < CREATE_RETRY_TIME && !mInterrupted; i++) { 126 try { 127 mBtServerSocket = mAdapter 128 .listenUsingInsecureRfcommOn(mBtOppRfcommChannel); 129 } catch (IOException e1) { 130 Log.e(TAG, "Error create RfcommServerSocket " + e1); 131 serverOK = false; 132 } 133 if (!serverOK) { 134 synchronized (this) { 135 try { 136 if (V) Log.v(TAG, "wait 3 seconds"); 137 Thread.sleep(3000); 138 } catch (InterruptedException e) { 139 Log.e(TAG, "socketAcceptThread thread was interrupted (3)"); 140 mInterrupted = true; 141 } 142 } 143 } else { 144 break; 145 } 146 } 147 if (!serverOK) { 148 Log.e(TAG, "Error start listening after " + CREATE_RETRY_TIME + " try"); 149 mInterrupted = true; 150 } 151 if (!mInterrupted) { 152 Log.i(TAG, "Accept thread started on channel " + mBtOppRfcommChannel); 153 } 154 BluetoothSocket clientSocket; 155 while (!mInterrupted) { 156 try { 157 clientSocket = mBtServerSocket.accept(); 158 Log.i(TAG, "Accepted connectoin from " 159 + clientSocket.getRemoteDevice()); 160 BluetoothOppRfcommTransport transport = new BluetoothOppRfcommTransport( 161 clientSocket); 162 Message msg = Message.obtain(); 163 msg.setTarget(mCallback); 164 msg.what = MSG_INCOMING_BTOPP_CONNECTION; 165 msg.obj = transport; 166 msg.sendToTarget(); 167 } catch (IOException e) { 168 Log.e(TAG, "Error accept connection " + e); 169 } 170 } 171 Log.i(TAG, "BluetoothSocket listen thread finished"); 172 } 173 } 174 }; 175 mInterrupted = false; 176 if(!Constants.USE_TCP_SIMPLE_SERVER) { 177 mSocketAcceptThread.start(); 178 } 179 } 180 return true; 181 } 182 183 public synchronized void stop() { 184 if (mSocketAcceptThread != null) { 185 Log.i(TAG, "stopping Accept Thread"); 186 187 mInterrupted = true; 188 if (Constants.USE_TCP_DEBUG) { 189 if (V) Log.v(TAG, "close mTcpServerSocket"); 190 if (mTcpServerSocket != null) { 191 try { 192 mTcpServerSocket.close(); 193 } catch (IOException e) { 194 Log.e(TAG, "Error close mTcpServerSocket"); 195 } 196 } 197 } else { 198 if (V) Log.v(TAG, "close mBtServerSocket"); 199 200 if (mBtServerSocket != null) { 201 try { 202 mBtServerSocket.close(); 203 } catch (IOException e) { 204 Log.e(TAG, "Error close mBtServerSocket"); 205 } 206 } 207 } 208 try { 209 mSocketAcceptThread.interrupt(); 210 if (V) Log.v(TAG, "waiting for thread to terminate"); 211 mSocketAcceptThread.join(); 212 mSocketAcceptThread = null; 213 mCallback = null; 214 } catch (InterruptedException e) { 215 if (V) Log.v(TAG, "Interrupted waiting for Accept Thread to join"); 216 } 217 } 218 } 219} 220