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