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