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