10b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly/*
20b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Copyright (C) 2009 The Android Open Source Project
30b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
40b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
50b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * you may not use this file except in compliance with the License.
60b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * You may obtain a copy of the License at
70b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
80b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
90b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
100b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Unless required by applicable law or agreed to in writing, software
110b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
120b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * See the License for the specific language governing permissions and
140b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * limitations under the License.
150b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */
160b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
170b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellypackage android.bluetooth;
180b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pellyimport android.os.Handler;
203b147b770269173d5d711d6c33f142dc5e723824zzyimport android.os.ParcelUuid;
21238e0f934f1f47263b384bc745ae0678c777130dCasper Bondeimport android.util.Log;
2224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
230b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.Closeable;
240b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.IOException;
250b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
260b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly/**
2745e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * A listening Bluetooth socket.
280b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
2945e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
3045e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
3145e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * side, use a {@link BluetoothServerSocket} to create a listening server
329fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * socket. When a connection is accepted by the {@link BluetoothServerSocket},
339fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * it will return a new {@link BluetoothSocket} to manage the connection.
34f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby * On the client side, use a single {@link BluetoothSocket} to both initiate
359fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * an outgoing connection and to manage the connection.
360b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
379fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p>The most common type of Bluetooth socket is RFCOMM, which is the type
389fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * supported by the Android APIs. RFCOMM is a connection-oriented, streaming
399fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * transport over Bluetooth. It is also known as the Serial Port Profile (SPP).
400b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
41f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby * <p>To create a listening {@link BluetoothServerSocket} that's ready for
429fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * incoming connections, use
439fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@link BluetoothAdapter#listenUsingRfcommWithServiceRecord
449fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * BluetoothAdapter.listenUsingRfcommWithServiceRecord()}. Then call
459fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@link #accept()} to listen for incoming connection requests. This call
469fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * will block until a connection is established, at which point, it will return
476d95fc0a2ca910212a43c4547c0ef000659b72dcScott Main * a {@link BluetoothSocket} to manage the connection. Once the {@link
486d95fc0a2ca910212a43c4547c0ef000659b72dcScott Main * BluetoothSocket} is acquired, it's a good idea to call {@link #close()} on
496d95fc0a2ca910212a43c4547c0ef000659b72dcScott Main * the {@link BluetoothServerSocket} when it's no longer needed for accepting
506d95fc0a2ca910212a43c4547c0ef000659b72dcScott Main * connections. Closing the {@link BluetoothServerSocket} will <em>not</em>
516d95fc0a2ca910212a43c4547c0ef000659b72dcScott Main * close the returned {@link BluetoothSocket}.
5245e2704ff512d41e22af2801d76e96955469ce8dNick Pelly *
539fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p>{@link BluetoothServerSocket} is thread
5445e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * safe. In particular, {@link #close} will always immediately abort ongoing
559fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * operations and close the server socket.
569fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main *
579fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p class="note"><strong>Note:</strong>
589fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * Requires the {@link android.Manifest.permission#BLUETOOTH} permission.
59cf44059813539bf7f36dabd278cef93ba3122c56Nick Pelly *
603aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference">
613aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3>
623aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about using Bluetooth, read the
633aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <a href="{@docRoot}guide/topics/wireless/bluetooth.html">Bluetooth</a> developer guide.</p>
643aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div>
653aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez *
669fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@see BluetoothSocket}
670b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */
680b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellypublic final class BluetoothServerSocket implements Closeable {
6971c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly
70238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private static final String TAG = "BluetoothServerSocket";
71bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /*package*/ final BluetoothSocket mSocket;
7224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    private Handler mHandler;
7324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    private int mMessage;
74238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private int mChannel;
750b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
760b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
770b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Construct a socket for incoming connections.
786a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly     * @param type    type of socket
796a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly     * @param auth    require the remote device to be authenticated
806a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly     * @param encrypt require the connection to be encrypted
816a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly     * @param port    remote port
820b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @throws IOException On error, for example Bluetooth not available, or
83f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby     *                     insufficient privileges
840b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
85bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
866a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly            throws IOException {
876d8b80dd8c56dba02dcb6e64ace37fb85aeee1f5Ben Dodson        mChannel = port;
8816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null);
892328423d19416da0c1068883c33e612d5729fc47Casper Bonde        if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
902328423d19416da0c1068883c33e612d5729fc47Casper Bonde            mSocket.setExcludeSdp(true);
912328423d19416da0c1068883c33e612d5729fc47Casper Bonde        }
922328423d19416da0c1068883c33e612d5729fc47Casper Bonde    }
932328423d19416da0c1068883c33e612d5729fc47Casper Bonde
942328423d19416da0c1068883c33e612d5729fc47Casper Bonde    /**
952328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * Construct a socket for incoming connections.
962328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param type    type of socket
972328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param auth    require the remote device to be authenticated
982328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param encrypt require the connection to be encrypted
992328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param port    remote port
1002328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param mitm    enforce man-in-the-middle protection for authentication.
1013b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde     * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection
1022328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @throws IOException On error, for example Bluetooth not available, or
1032328423d19416da0c1068883c33e612d5729fc47Casper Bonde     *                     insufficient privileges
1042328423d19416da0c1068883c33e612d5729fc47Casper Bonde     */
1052328423d19416da0c1068883c33e612d5729fc47Casper Bonde    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port,
1063b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde            boolean mitm, boolean min16DigitPin)
1072328423d19416da0c1068883c33e612d5729fc47Casper Bonde            throws IOException {
1082328423d19416da0c1068883c33e612d5729fc47Casper Bonde        mChannel = port;
1093b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null, mitm,
1103b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde                min16DigitPin);
111238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
112238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mSocket.setExcludeSdp(true);
113238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
1140b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1150b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1160b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
1173b147b770269173d5d711d6c33f142dc5e723824zzy     * Construct a socket for incoming connections.
1183b147b770269173d5d711d6c33f142dc5e723824zzy     * @param type    type of socket
1193b147b770269173d5d711d6c33f142dc5e723824zzy     * @param auth    require the remote device to be authenticated
1203b147b770269173d5d711d6c33f142dc5e723824zzy     * @param encrypt require the connection to be encrypted
1213b147b770269173d5d711d6c33f142dc5e723824zzy     * @param uuid    uuid
1223b147b770269173d5d711d6c33f142dc5e723824zzy     * @throws IOException On error, for example Bluetooth not available, or
1233b147b770269173d5d711d6c33f142dc5e723824zzy     *                     insufficient privileges
1243b147b770269173d5d711d6c33f142dc5e723824zzy     */
1253b147b770269173d5d711d6c33f142dc5e723824zzy    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, ParcelUuid uuid)
1263b147b770269173d5d711d6c33f142dc5e723824zzy            throws IOException {
1273b147b770269173d5d711d6c33f142dc5e723824zzy        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, -1, uuid);
128238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        // TODO: This is the same as mChannel = -1 - is this intentional?
1293b147b770269173d5d711d6c33f142dc5e723824zzy        mChannel = mSocket.getPort();
1303b147b770269173d5d711d6c33f142dc5e723824zzy    }
1313b147b770269173d5d711d6c33f142dc5e723824zzy
1323b147b770269173d5d711d6c33f142dc5e723824zzy
1333b147b770269173d5d711d6c33f142dc5e723824zzy    /**
1340b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Block until a connection is established.
13545e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>Returns a connected {@link BluetoothSocket} on successful connection.
13645e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>Once this call returns, it can be called again to accept subsequent
13745e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * incoming connections.
13845e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>{@link #close} can be used to abort this call from another thread.
13945e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * @return a connected {@link BluetoothSocket}
14045e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * @throws IOException on error, for example this call was aborted, or
14145e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     *                     timeout
1420b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
1430b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public BluetoothSocket accept() throws IOException {
1440b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        return accept(-1);
1450b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1460b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1470b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
1480b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Block until a connection is established, with timeout.
14945e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>Returns a connected {@link BluetoothSocket} on successful connection.
15045e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>Once this call returns, it can be called again to accept subsequent
15145e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * incoming connections.
15245e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>{@link #close} can be used to abort this call from another thread.
15345e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * @return a connected {@link BluetoothSocket}
15445e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * @throws IOException on error, for example this call was aborted, or
1550b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     *                     timeout
1560b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
1570b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public BluetoothSocket accept(int timeout) throws IOException {
15871c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly        return mSocket.accept(timeout);
1590b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1600b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1610b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
16245e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * Immediately close this socket, and release all associated resources.
16345e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>Causes blocked calls on this socket in other threads to immediately
1640b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * throw an IOException.
1656d95fc0a2ca910212a43c4547c0ef000659b72dcScott Main     * <p>Closing the {@link BluetoothServerSocket} will <em>not</em>
1666d95fc0a2ca910212a43c4547c0ef000659b72dcScott Main     * close any {@link BluetoothSocket} received from {@link #accept()}.
1670b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
1680b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public void close() throws IOException {
16924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        synchronized (this) {
17024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            if (mHandler != null) {
17124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly                mHandler.obtainMessage(mMessage).sendToTarget();
17224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            }
17324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
17471c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly        mSocket.close();
1750b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
17624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
17724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    /*package*/ synchronized void setCloseHandler(Handler handler, int message) {
17824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        mHandler = handler;
17924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        mMessage = message;
18024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    }
1813b147b770269173d5d711d6c33f142dc5e723824zzy    /*package*/ void setServiceName(String ServiceName) {
1823b147b770269173d5d711d6c33f142dc5e723824zzy        mSocket.setServiceName(ServiceName);
1833b147b770269173d5d711d6c33f142dc5e723824zzy    }
184238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
1856d8b80dd8c56dba02dcb6e64ace37fb85aeee1f5Ben Dodson    /**
1866d8b80dd8c56dba02dcb6e64ace37fb85aeee1f5Ben Dodson     * Returns the channel on which this socket is bound.
1876d8b80dd8c56dba02dcb6e64ace37fb85aeee1f5Ben Dodson     * @hide
1886d8b80dd8c56dba02dcb6e64ace37fb85aeee1f5Ben Dodson     */
1896d8b80dd8c56dba02dcb6e64ace37fb85aeee1f5Ben Dodson    public int getChannel() {
1906d8b80dd8c56dba02dcb6e64ace37fb85aeee1f5Ben Dodson        return mChannel;
1916d8b80dd8c56dba02dcb6e64ace37fb85aeee1f5Ben Dodson    }
192238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
193238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /**
194238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Sets the channel on which future sockets are bound.
195238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Currently used only when a channel is auto generated.
196238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     */
197238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /*package*/ void setChannel(int newChannel) {
198238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        /* TODO: From a design/architecture perspective this is wrong.
199238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         *       The bind operation should be conducted through this class
200238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         *       and the resulting port should be kept in mChannel, and
201238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         *       not set from BluetoothAdapter. */
202238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(mSocket != null) {
203238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(mSocket.getPort() != newChannel) {
204238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                Log.w(TAG,"The port set is different that the underlying port. mSocket.getPort(): "
205238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                            + mSocket.getPort() + " requested newChannel: " + newChannel);
206238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
207238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
208238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mChannel = newChannel;
209238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
210238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
211238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    @Override
212238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public String toString() {
213238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        StringBuilder sb = new StringBuilder();
214238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        sb.append("ServerSocket: Type: ");
215238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        switch(mSocket.getConnectionType()) {
216238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            case BluetoothSocket.TYPE_RFCOMM:
217238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            {
218238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                sb.append("TYPE_RFCOMM");
219238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                break;
220238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
221238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            case BluetoothSocket.TYPE_L2CAP:
222238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            {
223238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                sb.append("TYPE_L2CAP");
224238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                break;
225238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
226238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            case BluetoothSocket.TYPE_SCO:
227238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            {
228238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                sb.append("TYPE_SCO");
229238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                break;
230238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
231238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
232238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        sb.append(" Channel: ").append(mChannel);
233238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        return sb.toString();
234238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
2350b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly}
236