Home | History | Annotate | Download | only in opp
      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