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 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 
     73     public BluetoothOppRfcommListener(BluetoothAdapter adapter) {
     74         mAdapter = adapter;
     75     }
     76 
     77 
     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 
    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