10b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly/*
2fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Copyright (C) 2012 The Android Open Source Project
3fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu *
4fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Licensed under the Apache License, Version 2.0 (the "License");
5fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * you may not use this file except in compliance with the License.
6fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * You may obtain a copy of the License at
7fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu *
8fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu *      http://www.apache.org/licenses/LICENSE-2.0
9fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu *
10fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Unless required by applicable law or agreed to in writing, software
11fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * distributed under the License is distributed on an "AS IS" BASIS,
12fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * See the License for the specific language governing permissions and
14fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * limitations under the License.
150b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */
160b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
170b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellypackage android.bluetooth;
180b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.os.ParcelUuid;
203b147b770269173d5d711d6c33f142dc5e723824zzyimport android.os.ParcelFileDescriptor;
2116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.os.RemoteException;
2216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.util.Log;
2316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
24238e0f934f1f47263b384bc745ae0678c777130dCasper Bondeimport java.io.BufferedInputStream;
250b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.Closeable;
263b147b770269173d5d711d6c33f142dc5e723824zzyimport java.io.FileDescriptor;
270b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.IOException;
280b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.InputStream;
290b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.OutputStream;
30e6748ce31f18782b7a47a5b2eb251efd83e7b609Andreas Gampeimport java.util.Arrays;
31fea17de7aaa5729d3111102b2734b158403d2780Jeff Sharkeyimport java.util.Locale;
32b49a89635906e0901637a4a4c1c2f5bb263b6595zzyimport java.util.UUID;
333b147b770269173d5d711d6c33f142dc5e723824zzyimport android.net.LocalSocket;
34238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
35238e0f934f1f47263b384bc745ae0678c777130dCasper Bondeimport java.nio.Buffer;
363b147b770269173d5d711d6c33f142dc5e723824zzyimport java.nio.ByteOrder;
373b147b770269173d5d711d6c33f142dc5e723824zzyimport java.nio.ByteBuffer;
380b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly/**
3945e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * A connected or connecting Bluetooth socket.
400b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
4145e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
4245e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
4345e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * side, use a {@link BluetoothServerSocket} to create a listening server
449fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * socket. When a connection is accepted by the {@link BluetoothServerSocket},
459fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * it will return a new {@link BluetoothSocket} to manage the connection.
46f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby * On the client side, use a single {@link BluetoothSocket} to both initiate
479fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * an outgoing connection and to manage the connection.
480b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
499fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p>The most common type of Bluetooth socket is RFCOMM, which is the type
509fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * supported by the Android APIs. RFCOMM is a connection-oriented, streaming
519fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * transport over Bluetooth. It is also known as the Serial Port Profile (SPP).
520b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly *
539fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p>To create a {@link BluetoothSocket} for connecting to a known device, use
549fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@link BluetoothDevice#createRfcommSocketToServiceRecord
559fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * BluetoothDevice.createRfcommSocketToServiceRecord()}.
569fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * Then call {@link #connect()} to attempt a connection to the remote device.
579fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * This call will block until a connection is established or the connection
589fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * fails.
5945e2704ff512d41e22af2801d76e96955469ce8dNick Pelly *
609fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p>To create a {@link BluetoothSocket} as a server (or "host"), see the
619fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@link BluetoothServerSocket} documentation.
6245e2704ff512d41e22af2801d76e96955469ce8dNick Pelly *
639fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p>Once the socket is connected, whether initiated as a client or accepted
649fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * as a server, open the IO streams by calling {@link #getInputStream} and
659fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@link #getOutputStream} in order to retrieve {@link java.io.InputStream}
669fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * and {@link java.io.OutputStream} objects, respectively, which are
679fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * automatically connected to the socket.
689fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main *
699fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p>{@link BluetoothSocket} is thread
7045e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * safe. In particular, {@link #close} will always immediately abort ongoing
7145e2704ff512d41e22af2801d76e96955469ce8dNick Pelly * operations and close the socket.
72cf44059813539bf7f36dabd278cef93ba3122c56Nick Pelly *
739fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * <p class="note"><strong>Note:</strong>
749fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * Requires the {@link android.Manifest.permission#BLUETOOTH} permission.
759fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main *
763aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference">
773aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3>
783aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about using Bluetooth, read the
79382871b03fd6d1d1207d20cf647fa73e71a8496eMarie Janssen * <a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer guide.</p>
803aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div>
813aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez *
829fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@see BluetoothServerSocket}
839fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@see java.io.InputStream}
849fab0aef19a4633d2e4670564e5d7ae9e52fe11fScott Main * {@see java.io.OutputStream}
850b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */
860b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellypublic final class BluetoothSocket implements Closeable {
8716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    private static final String TAG = "BluetoothSocket";
88f3de98a2d09e2e84c0ca0eb55ab7cf7d943135d1Joe LaPenna    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
89f3de98a2d09e2e84c0ca0eb55ab7cf7d943135d1Joe LaPenna    private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
9016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
9124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    /** @hide */
9224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    public static final int MAX_RFCOMM_CHANNEL = 30;
93238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /*package*/ static final int MAX_L2CAP_PACKAGE_SIZE = 0xFFFF;
9424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
95f455986a45328614c8dd07a4d60a30b9ddc3d994Andre Eisenbach    /** RFCOMM socket */
96238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final int TYPE_RFCOMM = 1;
97f455986a45328614c8dd07a4d60a30b9ddc3d994Andre Eisenbach
98f455986a45328614c8dd07a4d60a30b9ddc3d994Andre Eisenbach    /** SCO socket */
99238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final int TYPE_SCO = 2;
100f455986a45328614c8dd07a4d60a30b9ddc3d994Andre Eisenbach
101f455986a45328614c8dd07a4d60a30b9ddc3d994Andre Eisenbach    /** L2CAP socket */
102238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final int TYPE_L2CAP = 3;
1036a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly
10424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    /*package*/ static final int EBADFD = 77;
10524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    /*package*/ static final int EADDRINUSE = 98;
10624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
1073b147b770269173d5d711d6c33f142dc5e723824zzy    /*package*/ static final int SEC_FLAG_ENCRYPT = 1;
1083b147b770269173d5d711d6c33f142dc5e723824zzy    /*package*/ static final int SEC_FLAG_AUTH = 1 << 1;
109238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /*package*/ static final int BTSOCK_FLAG_NO_SDP  = 1 << 2;
1102328423d19416da0c1068883c33e612d5729fc47Casper Bonde    /*package*/ static final int SEC_FLAG_AUTH_MITM  = 1 << 3;
1113b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde    /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT  = 1 << 4;
1123b147b770269173d5d711d6c33f142dc5e723824zzy
1136a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    private final int mType;  /* one of TYPE_RFCOMM etc */
1143b147b770269173d5d711d6c33f142dc5e723824zzy    private BluetoothDevice mDevice;    /* remote device */
1153b147b770269173d5d711d6c33f142dc5e723824zzy    private String mAddress;    /* remote address */
1160b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final boolean mAuth;
1170b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final boolean mEncrypt;
1180b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final BluetoothInputStream mInputStream;
1190b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final BluetoothOutputStream mOutputStream;
1203b147b770269173d5d711d6c33f142dc5e723824zzy    private final ParcelUuid mUuid;
1212328423d19416da0c1068883c33e612d5729fc47Casper Bonde    private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */
1222328423d19416da0c1068883c33e612d5729fc47Casper Bonde    private boolean mAuthMitm = false;   /* when true Man-in-the-middle protection will be enabled*/
1233b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde    private boolean mMin16DigitPin = false; /* Minimum 16 digit pin for sec mode 2 connections */
1243b147b770269173d5d711d6c33f142dc5e723824zzy    private ParcelFileDescriptor mPfd;
1253b147b770269173d5d711d6c33f142dc5e723824zzy    private LocalSocket mSocket;
1263b147b770269173d5d711d6c33f142dc5e723824zzy    private InputStream mSocketIS;
1273b147b770269173d5d711d6c33f142dc5e723824zzy    private OutputStream mSocketOS;
12868c692df5f667dcee42506d3c6459d3dc2e1cdd6Mike Lockwood    private int mPort;  /* RFCOMM channel or L2CAP psm */
1293b147b770269173d5d711d6c33f142dc5e723824zzy    private int mFd;
1303b147b770269173d5d711d6c33f142dc5e723824zzy    private String mServiceName;
1313b147b770269173d5d711d6c33f142dc5e723824zzy    private static int PROXY_CONNECTION_TIMEOUT = 5000;
1323b147b770269173d5d711d6c33f142dc5e723824zzy
133238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private static int SOCK_SIGNAL_SIZE = 20;
134238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
135238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private ByteBuffer mL2capBuffer = null;
136238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private int mMaxTxPacketSize = 0; // The l2cap maximum packet size supported by the peer.
137238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private int mMaxRxPacketSize = 0; // The l2cap maximum packet size that can be received.
1380b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
139ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie    private enum SocketState {
140ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie        INIT,
141ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie        CONNECTED,
1423b147b770269173d5d711d6c33f142dc5e723824zzy        LISTENING,
1433b147b770269173d5d711d6c33f142dc5e723824zzy        CLOSED,
144ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie    }
145ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie
14671c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly    /** prevents all native calls after destroyNative() */
1473b147b770269173d5d711d6c33f142dc5e723824zzy    private volatile SocketState mSocketState;
14871c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly
149ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie    /** protects mSocketState */
1503b147b770269173d5d711d6c33f142dc5e723824zzy    //private final ReentrantReadWriteLock mLock;
1510b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1520b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
153bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Construct a BluetoothSocket.
1546a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly     * @param type    type of socket
1550b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @param fd      fd to use for connected socket, or -1 for a new socket
1560b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @param auth    require the remote device to be authenticated
1570b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @param encrypt require the connection to be encrypted
158bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param device  remote device that this socket can connect to
1590b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @param port    remote port
16016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * @param uuid    SDP uuid
1610b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @throws IOException On error, for example Bluetooth not available, or
162f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby     *                     insufficient privileges
1630b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
164bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
16516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            BluetoothDevice device, int port, ParcelUuid uuid) throws IOException {
1663b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde        this(type, fd, auth, encrypt, device, port, uuid, false, false);
1672328423d19416da0c1068883c33e612d5729fc47Casper Bonde    }
1682328423d19416da0c1068883c33e612d5729fc47Casper Bonde
1692328423d19416da0c1068883c33e612d5729fc47Casper Bonde    /**
1702328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * Construct a BluetoothSocket.
1712328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param type    type of socket
1722328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param fd      fd to use for connected socket, or -1 for a new socket
1732328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param auth    require the remote device to be authenticated
1742328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param encrypt require the connection to be encrypted
1752328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param device  remote device that this socket can connect to
1762328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param port    remote port
1772328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param uuid    SDP uuid
1782328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @param mitm    enforce man-in-the-middle protection.
1793b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde     * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection
1802328423d19416da0c1068883c33e612d5729fc47Casper Bonde     * @throws IOException On error, for example Bluetooth not available, or
1812328423d19416da0c1068883c33e612d5729fc47Casper Bonde     *                     insufficient privileges
1822328423d19416da0c1068883c33e612d5729fc47Casper Bonde     */
1832328423d19416da0c1068883c33e612d5729fc47Casper Bonde    /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
1843b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde            BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin)
1853b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde                    throws IOException {
186238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type);
187238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1
188238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
18924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            if (port < 1 || port > MAX_RFCOMM_CHANNEL) {
19024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly                throw new IOException("Invalid RFCOMM channel: " + port);
19124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            }
19224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
193238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if (uuid != null)
194b49a89635906e0901637a4a4c1c2f5bb263b6595zzy            mUuid = uuid;
195b49a89635906e0901637a4a4c1c2f5bb263b6595zzy        else mUuid = new ParcelUuid(new UUID(0, 0));
1966a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly        mType = type;
1970b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mAuth = auth;
1982328423d19416da0c1068883c33e612d5729fc47Casper Bonde        mAuthMitm = mitm;
1993b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde        mMin16DigitPin = min16DigitPin;
2000b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mEncrypt = encrypt;
201bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mDevice = device;
2023b147b770269173d5d711d6c33f142dc5e723824zzy        mPort = port;
2033b147b770269173d5d711d6c33f142dc5e723824zzy        mFd = fd;
2043b147b770269173d5d711d6c33f142dc5e723824zzy
2053b147b770269173d5d711d6c33f142dc5e723824zzy        mSocketState = SocketState.INIT;
2063b147b770269173d5d711d6c33f142dc5e723824zzy
207bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        if (device == null) {
2083b147b770269173d5d711d6c33f142dc5e723824zzy            // Server socket
2093b147b770269173d5d711d6c33f142dc5e723824zzy            mAddress = BluetoothAdapter.getDefaultAdapter().getAddress();
210bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        } else {
2113b147b770269173d5d711d6c33f142dc5e723824zzy            // Remote socket
212bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            mAddress = device.getAddress();
213bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        }
2143b147b770269173d5d711d6c33f142dc5e723824zzy        mInputStream = new BluetoothInputStream(this);
2153b147b770269173d5d711d6c33f142dc5e723824zzy        mOutputStream = new BluetoothOutputStream(this);
2163b147b770269173d5d711d6c33f142dc5e723824zzy    }
2173b147b770269173d5d711d6c33f142dc5e723824zzy    private BluetoothSocket(BluetoothSocket s) {
218238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if (VDBG) Log.d(TAG, "Creating new Private BluetoothSocket of type: " + s.mType);
2193b147b770269173d5d711d6c33f142dc5e723824zzy        mUuid = s.mUuid;
2203b147b770269173d5d711d6c33f142dc5e723824zzy        mType = s.mType;
2213b147b770269173d5d711d6c33f142dc5e723824zzy        mAuth = s.mAuth;
2223b147b770269173d5d711d6c33f142dc5e723824zzy        mEncrypt = s.mEncrypt;
2233b147b770269173d5d711d6c33f142dc5e723824zzy        mPort = s.mPort;
2240b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mInputStream = new BluetoothInputStream(this);
2250b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mOutputStream = new BluetoothOutputStream(this);
226238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mMaxRxPacketSize = s.mMaxRxPacketSize;
227238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mMaxTxPacketSize = s.mMaxTxPacketSize;
228238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
2293b147b770269173d5d711d6c33f142dc5e723824zzy        mServiceName = s.mServiceName;
230238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mExcludeSdp = s.mExcludeSdp;
2312328423d19416da0c1068883c33e612d5729fc47Casper Bonde        mAuthMitm = s.mAuthMitm;
2323b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde        mMin16DigitPin = s.mMin16DigitPin;
2333b147b770269173d5d711d6c33f142dc5e723824zzy    }
2343b147b770269173d5d711d6c33f142dc5e723824zzy    private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException {
2353b147b770269173d5d711d6c33f142dc5e723824zzy        BluetoothSocket as = new BluetoothSocket(this);
2363b147b770269173d5d711d6c33f142dc5e723824zzy        as.mSocketState = SocketState.CONNECTED;
2373b147b770269173d5d711d6c33f142dc5e723824zzy        FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors();
238e6748ce31f18782b7a47a5b2eb251efd83e7b609Andreas Gampe        if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + Arrays.toString(fds));
2393b147b770269173d5d711d6c33f142dc5e723824zzy        if(fds == null || fds.length != 1) {
240e6748ce31f18782b7a47a5b2eb251efd83e7b609Andreas Gampe            Log.e(TAG, "socket fd passed from stack failed, fds: " + Arrays.toString(fds));
24171bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy            as.close();
2423b147b770269173d5d711d6c33f142dc5e723824zzy            throw new IOException("bt socket acept failed");
2433b147b770269173d5d711d6c33f142dc5e723824zzy        }
244569ff225a3879363bb31548a664161fee5270a0dZach Johnson
245569ff225a3879363bb31548a664161fee5270a0dZach Johnson        as.mPfd = new ParcelFileDescriptor(fds[0]);
2467fd724611b8113c7f584c603d14fd44071cad799Neil Fuller        as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]);
2473b147b770269173d5d711d6c33f142dc5e723824zzy        as.mSocketIS = as.mSocket.getInputStream();
2483b147b770269173d5d711d6c33f142dc5e723824zzy        as.mSocketOS = as.mSocket.getOutputStream();
2493b147b770269173d5d711d6c33f142dc5e723824zzy        as.mAddress = RemoteAddr;
2503b147b770269173d5d711d6c33f142dc5e723824zzy        as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(RemoteAddr);
2513b147b770269173d5d711d6c33f142dc5e723824zzy        return as;
2520b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
253bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /**
25416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * Construct a BluetoothSocket from address. Used by native code.
255bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param type    type of socket
256bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param fd      fd to use for connected socket, or -1 for a new socket
257bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param auth    require the remote device to be authenticated
258bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param encrypt require the connection to be encrypted
259bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param address remote device that this socket can connect to
260bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param port    remote port
261bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @throws IOException On error, for example Bluetooth not available, or
262f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby     *                     insufficient privileges
263bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     */
264bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address,
265bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            int port) throws IOException {
2663b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde        this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null, false, false);
267bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    }
268bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly
26945e2704ff512d41e22af2801d76e96955469ce8dNick Pelly    /** @hide */
2700b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    @Override
2710b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    protected void finalize() throws Throwable {
2720b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        try {
2730b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly            close();
2740b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        } finally {
2750b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly            super.finalize();
2760b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        }
2770b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
2783b147b770269173d5d711d6c33f142dc5e723824zzy    private int getSecurityFlags() {
2793b147b770269173d5d711d6c33f142dc5e723824zzy        int flags = 0;
2803b147b770269173d5d711d6c33f142dc5e723824zzy        if(mAuth)
2813b147b770269173d5d711d6c33f142dc5e723824zzy            flags |= SEC_FLAG_AUTH;
2823b147b770269173d5d711d6c33f142dc5e723824zzy        if(mEncrypt)
2833b147b770269173d5d711d6c33f142dc5e723824zzy            flags |= SEC_FLAG_ENCRYPT;
284238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(mExcludeSdp)
285238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            flags |= BTSOCK_FLAG_NO_SDP;
2862328423d19416da0c1068883c33e612d5729fc47Casper Bonde        if(mAuthMitm)
2872328423d19416da0c1068883c33e612d5729fc47Casper Bonde            flags |= SEC_FLAG_AUTH_MITM;
2883b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde        if(mMin16DigitPin)
2893b3d1fea94318a4892fbd4353269749af417a81aCasper Bonde            flags |= SEC_FLAG_AUTH_16_DIGIT;
2903b147b770269173d5d711d6c33f142dc5e723824zzy        return flags;
2910b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
2920b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
2930b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
29445e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * Get the remote device this socket is connecting, or connected, to.
29545e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * @return remote device
2960b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
297bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public BluetoothDevice getRemoteDevice() {
298bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        return mDevice;
2990b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
3000b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
3010b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
3020b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Get the input stream associated with this socket.
30345e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>The input stream will be returned even if the socket is not yet
3040b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * connected, but operations on that stream will throw IOException until
3050b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * the associated socket is connected.
3060b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @return InputStream
3070b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
3080b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public InputStream getInputStream() throws IOException {
3090b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        return mInputStream;
3100b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
3110b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
3120b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
3130b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Get the output stream associated with this socket.
31445e2704ff512d41e22af2801d76e96955469ce8dNick Pelly     * <p>The output stream will be returned even if the socket is not yet
3150b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * connected, but operations on that stream will throw IOException until
3160b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * the associated socket is connected.
3170b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @return OutputStream
3180b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
3190b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public OutputStream getOutputStream() throws IOException {
3200b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        return mOutputStream;
3210b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
3220b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
32324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    /**
324ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie     * Get the connection status of this socket, ie, whether there is an active connection with
325ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie     * remote device.
326ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie     * @return true if connected
327ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie     *         false if not connected
328ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie     */
329ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie    public boolean isConnected() {
3303b147b770269173d5d711d6c33f142dc5e723824zzy        return mSocketState == SocketState.CONNECTED;
3313b147b770269173d5d711d6c33f142dc5e723824zzy    }
3323b147b770269173d5d711d6c33f142dc5e723824zzy
3333b147b770269173d5d711d6c33f142dc5e723824zzy    /*package*/ void setServiceName(String name) {
3343b147b770269173d5d711d6c33f142dc5e723824zzy        mServiceName = name;
3353b147b770269173d5d711d6c33f142dc5e723824zzy    }
3363b147b770269173d5d711d6c33f142dc5e723824zzy
3373b147b770269173d5d711d6c33f142dc5e723824zzy    /**
3383b147b770269173d5d711d6c33f142dc5e723824zzy     * Attempt to connect to a remote device.
3393b147b770269173d5d711d6c33f142dc5e723824zzy     * <p>This method will block until a connection is made or the connection
3403b147b770269173d5d711d6c33f142dc5e723824zzy     * fails. If this method returns without an exception then this socket
3413b147b770269173d5d711d6c33f142dc5e723824zzy     * is now connected.
3423b147b770269173d5d711d6c33f142dc5e723824zzy     * <p>Creating new connections to
3433b147b770269173d5d711d6c33f142dc5e723824zzy     * remote Bluetooth devices should not be attempted while device discovery
3443b147b770269173d5d711d6c33f142dc5e723824zzy     * is in progress. Device discovery is a heavyweight procedure on the
3453b147b770269173d5d711d6c33f142dc5e723824zzy     * Bluetooth adapter and will significantly slow a device connection.
3463b147b770269173d5d711d6c33f142dc5e723824zzy     * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing
3473b147b770269173d5d711d6c33f142dc5e723824zzy     * discovery. Discovery is not managed by the Activity,
3483b147b770269173d5d711d6c33f142dc5e723824zzy     * but is run as a system service, so an application should always call
3493b147b770269173d5d711d6c33f142dc5e723824zzy     * {@link BluetoothAdapter#cancelDiscovery()} even if it
3503b147b770269173d5d711d6c33f142dc5e723824zzy     * did not directly request a discovery, just to be sure.
3513b147b770269173d5d711d6c33f142dc5e723824zzy     * <p>{@link #close} can be used to abort this call from another thread.
3523b147b770269173d5d711d6c33f142dc5e723824zzy     * @throws IOException on error, for example connection failure
3533b147b770269173d5d711d6c33f142dc5e723824zzy     */
3543b147b770269173d5d711d6c33f142dc5e723824zzy    public void connect() throws IOException {
3553b147b770269173d5d711d6c33f142dc5e723824zzy        if (mDevice == null) throw new IOException("Connect is called on null device");
3563b147b770269173d5d711d6c33f142dc5e723824zzy
3573b147b770269173d5d711d6c33f142dc5e723824zzy        try {
3583b147b770269173d5d711d6c33f142dc5e723824zzy            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
359238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            IBluetooth bluetoothProxy =
360238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
3610f42037eb7b5118015c2caca635538324ccf0ccffredc            if (bluetoothProxy == null) throw new IOException("Bluetooth is off");
3620f42037eb7b5118015c2caca635538324ccf0ccffredc            mPfd = bluetoothProxy.connectSocket(mDevice, mType,
3633b147b770269173d5d711d6c33f142dc5e723824zzy                    mUuid, mPort, getSecurityFlags());
3643b147b770269173d5d711d6c33f142dc5e723824zzy            synchronized(this)
3653b147b770269173d5d711d6c33f142dc5e723824zzy            {
366563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
3673b147b770269173d5d711d6c33f142dc5e723824zzy                if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
3683b147b770269173d5d711d6c33f142dc5e723824zzy                if (mPfd == null) throw new IOException("bt socket connect failed");
3693b147b770269173d5d711d6c33f142dc5e723824zzy                FileDescriptor fd = mPfd.getFileDescriptor();
3707fd724611b8113c7f584c603d14fd44071cad799Neil Fuller                mSocket = LocalSocket.createConnectedLocalSocket(fd);
3713b147b770269173d5d711d6c33f142dc5e723824zzy                mSocketIS = mSocket.getInputStream();
3723b147b770269173d5d711d6c33f142dc5e723824zzy                mSocketOS = mSocket.getOutputStream();
3733b147b770269173d5d711d6c33f142dc5e723824zzy            }
3743b147b770269173d5d711d6c33f142dc5e723824zzy            int channel = readInt(mSocketIS);
3753b147b770269173d5d711d6c33f142dc5e723824zzy            if (channel <= 0)
3763b147b770269173d5d711d6c33f142dc5e723824zzy                throw new IOException("bt socket connect failed");
3773b147b770269173d5d711d6c33f142dc5e723824zzy            mPort = channel;
3783b147b770269173d5d711d6c33f142dc5e723824zzy            waitSocketSignal(mSocketIS);
3793b147b770269173d5d711d6c33f142dc5e723824zzy            synchronized(this)
3803b147b770269173d5d711d6c33f142dc5e723824zzy            {
3813b147b770269173d5d711d6c33f142dc5e723824zzy                if (mSocketState == SocketState.CLOSED)
3823b147b770269173d5d711d6c33f142dc5e723824zzy                    throw new IOException("bt socket closed");
3833b147b770269173d5d711d6c33f142dc5e723824zzy                mSocketState = SocketState.CONNECTED;
3843b147b770269173d5d711d6c33f142dc5e723824zzy            }
3853b147b770269173d5d711d6c33f142dc5e723824zzy        } catch (RemoteException e) {
3863b147b770269173d5d711d6c33f142dc5e723824zzy            Log.e(TAG, Log.getStackTraceString(new Throwable()));
3873e8eb40950f4d02322ded64503314b7db2bf9825Sharvil Nanavati            throw new IOException("unable to send RPC: " + e.getMessage());
3883b147b770269173d5d711d6c33f142dc5e723824zzy        }
389ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie    }
390ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie
391ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie    /**
39224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly     * Currently returns unix errno instead of throwing IOException,
39324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly     * so that BluetoothAdapter can check the error code for EADDRINUSE
39424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly     */
39524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    /*package*/ int bindListen() {
3963b147b770269173d5d711d6c33f142dc5e723824zzy        int ret;
3973b147b770269173d5d711d6c33f142dc5e723824zzy        if (mSocketState == SocketState.CLOSED) return EBADFD;
398903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
3990f42037eb7b5118015c2caca635538324ccf0ccffredc        if (bluetoothProxy == null) {
4000f42037eb7b5118015c2caca635538324ccf0ccffredc            Log.e(TAG, "bindListen fail, reason: bluetooth is off");
4010f42037eb7b5118015c2caca635538324ccf0ccffredc            return -1;
4020f42037eb7b5118015c2caca635538324ccf0ccffredc        }
40371c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly        try {
4040f42037eb7b5118015c2caca635538324ccf0ccffredc            mPfd = bluetoothProxy.createSocketChannel(mType, mServiceName,
4053b147b770269173d5d711d6c33f142dc5e723824zzy                    mUuid, mPort, getSecurityFlags());
4063b147b770269173d5d711d6c33f142dc5e723824zzy        } catch (RemoteException e) {
4073b147b770269173d5d711d6c33f142dc5e723824zzy            Log.e(TAG, Log.getStackTraceString(new Throwable()));
4083b147b770269173d5d711d6c33f142dc5e723824zzy            return -1;
4093b147b770269173d5d711d6c33f142dc5e723824zzy        }
41071c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly
4113b147b770269173d5d711d6c33f142dc5e723824zzy        // read out port number
41271c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly        try {
4133b147b770269173d5d711d6c33f142dc5e723824zzy            synchronized(this) {
414f3de98a2d09e2e84c0ca0eb55ab7cf7d943135d1Joe LaPenna                if (DBG) Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " +
415563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                                mPfd);
4163b147b770269173d5d711d6c33f142dc5e723824zzy                if(mSocketState != SocketState.INIT) return EBADFD;
4173b147b770269173d5d711d6c33f142dc5e723824zzy                if(mPfd == null) return -1;
4183b147b770269173d5d711d6c33f142dc5e723824zzy                FileDescriptor fd = mPfd.getFileDescriptor();
419fc61da5ada4e96822a6bf6646437615af5632be3Ajay Panicker                if (fd == null) {
420fc61da5ada4e96822a6bf6646437615af5632be3Ajay Panicker                    Log.e(TAG, "bindListen(), null file descriptor");
421fc61da5ada4e96822a6bf6646437615af5632be3Ajay Panicker                    return -1;
422fc61da5ada4e96822a6bf6646437615af5632be3Ajay Panicker                }
423fc61da5ada4e96822a6bf6646437615af5632be3Ajay Panicker
4247fd724611b8113c7f584c603d14fd44071cad799Neil Fuller                if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket");
4257fd724611b8113c7f584c603d14fd44071cad799Neil Fuller                mSocket = LocalSocket.createConnectedLocalSocket(fd);
4267fd724611b8113c7f584c603d14fd44071cad799Neil Fuller                if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
4273b147b770269173d5d711d6c33f142dc5e723824zzy                mSocketIS = mSocket.getInputStream();
4283b147b770269173d5d711d6c33f142dc5e723824zzy                mSocketOS = mSocket.getOutputStream();
4293b147b770269173d5d711d6c33f142dc5e723824zzy            }
430f3de98a2d09e2e84c0ca0eb55ab7cf7d943135d1Joe LaPenna            if (DBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS);
4313b147b770269173d5d711d6c33f142dc5e723824zzy            int channel = readInt(mSocketIS);
4323b147b770269173d5d711d6c33f142dc5e723824zzy            synchronized(this) {
4333b147b770269173d5d711d6c33f142dc5e723824zzy                if(mSocketState == SocketState.INIT)
4343b147b770269173d5d711d6c33f142dc5e723824zzy                    mSocketState = SocketState.LISTENING;
4353b147b770269173d5d711d6c33f142dc5e723824zzy            }
436f3de98a2d09e2e84c0ca0eb55ab7cf7d943135d1Joe LaPenna            if (DBG) Log.d(TAG, "channel: " + channel);
437238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (mPort <= -1) {
4383b147b770269173d5d711d6c33f142dc5e723824zzy                mPort = channel;
4393b147b770269173d5d711d6c33f142dc5e723824zzy            } // else ASSERT(mPort == channel)
4403b147b770269173d5d711d6c33f142dc5e723824zzy            ret = 0;
4413b147b770269173d5d711d6c33f142dc5e723824zzy        } catch (IOException e) {
442726652e9d3f1adf6b68dedfa4618b490b7f1b4a3Matthew Xie            if (mPfd != null) {
443726652e9d3f1adf6b68dedfa4618b490b7f1b4a3Matthew Xie                try {
444726652e9d3f1adf6b68dedfa4618b490b7f1b4a3Matthew Xie                    mPfd.close();
445726652e9d3f1adf6b68dedfa4618b490b7f1b4a3Matthew Xie                } catch (IOException e1) {
446726652e9d3f1adf6b68dedfa4618b490b7f1b4a3Matthew Xie                    Log.e(TAG, "bindListen, close mPfd: " + e1);
447726652e9d3f1adf6b68dedfa4618b490b7f1b4a3Matthew Xie                }
448726652e9d3f1adf6b68dedfa4618b490b7f1b4a3Matthew Xie                mPfd = null;
449726652e9d3f1adf6b68dedfa4618b490b7f1b4a3Matthew Xie            }
4503b147b770269173d5d711d6c33f142dc5e723824zzy            Log.e(TAG, "bindListen, fail to get port number, exception: " + e);
4513b147b770269173d5d711d6c33f142dc5e723824zzy            return -1;
4523b147b770269173d5d711d6c33f142dc5e723824zzy        }
4533b147b770269173d5d711d6c33f142dc5e723824zzy        return ret;
4543b147b770269173d5d711d6c33f142dc5e723824zzy    }
455ceb6c9f517ede73bfb677e55fda9d9db6089ae69Matthew Xie
4563b147b770269173d5d711d6c33f142dc5e723824zzy    /*package*/ BluetoothSocket accept(int timeout) throws IOException {
4573b147b770269173d5d711d6c33f142dc5e723824zzy        BluetoothSocket acceptedSocket;
458238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if (mSocketState != SocketState.LISTENING)
459238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            throw new IOException("bt socket is not in listen state");
460652678af4d18b9a6c18ce6a860de01d958bc82fezzy        if(timeout > 0) {
461652678af4d18b9a6c18ce6a860de01d958bc82fezzy            Log.d(TAG, "accept() set timeout (ms):" + timeout);
462652678af4d18b9a6c18ce6a860de01d958bc82fezzy           mSocket.setSoTimeout(timeout);
463652678af4d18b9a6c18ce6a860de01d958bc82fezzy        }
4643b147b770269173d5d711d6c33f142dc5e723824zzy        String RemoteAddr = waitSocketSignal(mSocketIS);
465652678af4d18b9a6c18ce6a860de01d958bc82fezzy        if(timeout > 0)
466652678af4d18b9a6c18ce6a860de01d958bc82fezzy            mSocket.setSoTimeout(0);
4673b147b770269173d5d711d6c33f142dc5e723824zzy        synchronized(this)
4683b147b770269173d5d711d6c33f142dc5e723824zzy        {
4693b147b770269173d5d711d6c33f142dc5e723824zzy            if (mSocketState != SocketState.LISTENING)
4703b147b770269173d5d711d6c33f142dc5e723824zzy                throw new IOException("bt socket is not in listen state");
4713b147b770269173d5d711d6c33f142dc5e723824zzy            acceptedSocket = acceptSocket(RemoteAddr);
4723b147b770269173d5d711d6c33f142dc5e723824zzy            //quick drop the reference of the file handle
47371c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly        }
4743b147b770269173d5d711d6c33f142dc5e723824zzy        return acceptedSocket;
47571c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly    }
47671c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly
47771c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly    /*package*/ int available() throws IOException {
478563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) Log.d(TAG, "available: " + mSocketIS);
4793b147b770269173d5d711d6c33f142dc5e723824zzy        return mSocketIS.available();
48071c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly    }
48171bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy    /**
48271bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy     * Wait until the data in sending queue is emptied. A polling version
48371bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy     * for flush implementation. Used to ensure the writing data afterwards will
48471bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy     * be packed in new RFCOMM frame.
48571bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy     * @throws IOException
48671bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy     *             if an i/o error occurs.
48771bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy     */
48871bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy    /*package*/ void flush() throws IOException {
489610770d7129a33fdca5c23939f9ee0a80d0322f9Zhihai Xu        if (mSocketOS == null) throw new IOException("flush is called on null OutputStream");
49071bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy        if (VDBG) Log.d(TAG, "flush: " + mSocketOS);
49171bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy        mSocketOS.flush();
49271bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy    }
49371c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly
49471c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly    /*package*/ int read(byte[] b, int offset, int length) throws IOException {
495238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        int ret = 0;
496610770d7129a33fdca5c23939f9ee0a80d0322f9Zhihai Xu        if (VDBG) Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
497238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(mType == TYPE_L2CAP)
498238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        {
499238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            int bytesToRead = length;
500238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (VDBG) Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length
501238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    + "mL2capBuffer= " + mL2capBuffer);
502238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (mL2capBuffer == null) {
503238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                createL2capRxBuffer();
504238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
505238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (mL2capBuffer.remaining() == 0) {
506238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                if (VDBG) Log.v(TAG, "l2cap buffer empty, refilling...");
507238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                if (fillL2capRxBuffer() == -1) {
508238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    return -1;
509238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                }
510238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
511238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (bytesToRead > mL2capBuffer.remaining()) {
512238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                bytesToRead = mL2capBuffer.remaining();
513238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
514238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(VDBG) Log.v(TAG, "get(): offset: " + offset
515238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    + " bytesToRead: " + bytesToRead);
516238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mL2capBuffer.get(b, offset, bytesToRead);
517238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            ret = bytesToRead;
518238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }else {
519238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (VDBG) Log.v(TAG, "default: read(): offset: " + offset + " length:" + length);
520238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            ret = mSocketIS.read(b, offset, length);
521238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
522238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if (ret < 0)
523610770d7129a33fdca5c23939f9ee0a80d0322f9Zhihai Xu            throw new IOException("bt socket closed, read return: " + ret);
524610770d7129a33fdca5c23939f9ee0a80d0322f9Zhihai Xu        if (VDBG) Log.d(TAG, "read out:  " + mSocketIS + " ret: " + ret);
525610770d7129a33fdca5c23939f9ee0a80d0322f9Zhihai Xu        return ret;
52671c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly    }
52771c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly
52871c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly    /*package*/ int write(byte[] b, int offset, int length) throws IOException {
529238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
530238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        //TODO: Since bindings can exist between the SDU size and the
531238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        //      protocol, we might need to throw an exception instead of just
532238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        //      splitting the write into multiple smaller writes.
533238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        //      Rfcomm uses dynamic allocation, and should not have any bindings
534238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        //      to the actual message length.
535238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
536238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (mType == TYPE_L2CAP) {
537238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                if(length <= mMaxTxPacketSize) {
538238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    mSocketOS.write(b, offset, length);
539238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                } else {
540238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    if(DBG) Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n"
541238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                            + "Packet will be divided into SDU packets of size "
542238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                            + mMaxTxPacketSize);
543fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                    int tmpOffset = offset;
544fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                    int bytesToWrite = length;
545fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                    while (bytesToWrite > 0) {
546fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                        int tmpLength = (bytesToWrite > mMaxTxPacketSize)
547fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                                ? mMaxTxPacketSize
548fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                                : bytesToWrite;
549238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                        mSocketOS.write(b, tmpOffset, tmpLength);
550fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                        tmpOffset += tmpLength;
551fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                        bytesToWrite -= tmpLength;
552fc59c344bfd792674d9bfa388c4afe8bc00a90a4Christine Hallstrom                    }
553238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                }
554238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            } else {
555238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                mSocketOS.write(b, offset, length);
556238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
557238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // There is no good way to confirm since the entire process is asynchronous anyway
558238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
559238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            return length;
5603b147b770269173d5d711d6c33f142dc5e723824zzy    }
5613b147b770269173d5d711d6c33f142dc5e723824zzy
5623b147b770269173d5d711d6c33f142dc5e723824zzy    @Override
5633b147b770269173d5d711d6c33f142dc5e723824zzy    public void close() throws IOException {
564fc61da5ada4e96822a6bf6646437615af5632be3Ajay Panicker        Log.d(TAG, "close() this: " + this + ", channel: " + mPort +
565fc61da5ada4e96822a6bf6646437615af5632be3Ajay Panicker            ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS +
566fc61da5ada4e96822a6bf6646437615af5632be3Ajay Panicker            "mSocket: " + mSocket + ", mSocketState: " + mSocketState);
5673b147b770269173d5d711d6c33f142dc5e723824zzy        if(mSocketState == SocketState.CLOSED)
5683b147b770269173d5d711d6c33f142dc5e723824zzy            return;
5693b147b770269173d5d711d6c33f142dc5e723824zzy        else
5703b147b770269173d5d711d6c33f142dc5e723824zzy        {
5713b147b770269173d5d711d6c33f142dc5e723824zzy            synchronized(this)
5723b147b770269173d5d711d6c33f142dc5e723824zzy            {
5733b147b770269173d5d711d6c33f142dc5e723824zzy                 if(mSocketState == SocketState.CLOSED)
5743b147b770269173d5d711d6c33f142dc5e723824zzy                    return;
5753b147b770269173d5d711d6c33f142dc5e723824zzy                 mSocketState = SocketState.CLOSED;
5763b147b770269173d5d711d6c33f142dc5e723824zzy                 if(mSocket != null) {
577f3de98a2d09e2e84c0ca0eb55ab7cf7d943135d1Joe LaPenna                    if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket);
5783b147b770269173d5d711d6c33f142dc5e723824zzy                    mSocket.shutdownInput();
5793b147b770269173d5d711d6c33f142dc5e723824zzy                    mSocket.shutdownOutput();
5803b147b770269173d5d711d6c33f142dc5e723824zzy                    mSocket.close();
5813b147b770269173d5d711d6c33f142dc5e723824zzy                    mSocket = null;
5823b147b770269173d5d711d6c33f142dc5e723824zzy                }
58301771021e38f9dedce7910c81fea26a9bf837d9dZhihai Xu                if (mPfd != null) {
58401771021e38f9dedce7910c81fea26a9bf837d9dZhihai Xu                    mPfd.close();
58501771021e38f9dedce7910c81fea26a9bf837d9dZhihai Xu                    mPfd = null;
58601771021e38f9dedce7910c81fea26a9bf837d9dZhihai Xu                }
5873b147b770269173d5d711d6c33f142dc5e723824zzy           }
58871c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly        }
58971c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly    }
59071c3c7806acb2b2b7b8441817c26a2101d447bbeNick Pelly
5913b147b770269173d5d711d6c33f142dc5e723824zzy    /*package */ void removeChannel() {
5923b147b770269173d5d711d6c33f142dc5e723824zzy    }
59316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
5943b147b770269173d5d711d6c33f142dc5e723824zzy    /*package */ int getPort() {
5953b147b770269173d5d711d6c33f142dc5e723824zzy        return mPort;
5963b147b770269173d5d711d6c33f142dc5e723824zzy    }
597238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
598238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /**
599238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Get the maximum supported Transmit packet size for the underlying transport.
600238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Use this to optimize the writes done to the output socket, to avoid sending
601238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * half full packets.
602238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * @return the maximum supported Transmit packet size for the underlying transport.
603238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     */
604238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public int getMaxTransmitPacketSize(){
605238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        return mMaxTxPacketSize;
606238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
607238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
608238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /**
609238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Get the maximum supported Receive packet size for the underlying transport.
610238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Use this to optimize the reads done on the input stream, as any call to read
611238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * will return a maximum of this amount of bytes - or for some transports a
612238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * multiple of this value.
613238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * @return the maximum supported Receive packet size for the underlying transport.
614238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     */
615238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public int getMaxReceivePacketSize(){
616238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        return mMaxRxPacketSize;
617238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
618238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
619238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /**
620f455986a45328614c8dd07a4d60a30b9ddc3d994Andre Eisenbach     * Get the type of the underlying connection.
621f455986a45328614c8dd07a4d60a30b9ddc3d994Andre Eisenbach     * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP}
622238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     */
623238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public int getConnectionType() {
624238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        return mType;
625238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
626238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
627238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /**
628238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Change if a SDP entry should be automatically created.
629238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Must be called before calling .bind, for the call to have any effect.
630238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * @param mExcludeSdp <li>TRUE  - do not auto generate SDP record.
631238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     *                    <li>FALSE - default - auto generate SPP SDP record.
632238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * @hide
633238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     */
634238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public void setExcludeSdp(boolean excludeSdp) {
635238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        this.mExcludeSdp = excludeSdp;
636238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
637238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
6383b147b770269173d5d711d6c33f142dc5e723824zzy    private String convertAddr(final byte[] addr)  {
639fea17de7aaa5729d3111102b2734b158403d2780Jeff Sharkey        return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
6403b147b770269173d5d711d6c33f142dc5e723824zzy                addr[0] , addr[1], addr[2], addr[3] , addr[4], addr[5]);
6413b147b770269173d5d711d6c33f142dc5e723824zzy    }
6423b147b770269173d5d711d6c33f142dc5e723824zzy    private String waitSocketSignal(InputStream is) throws IOException {
6433b147b770269173d5d711d6c33f142dc5e723824zzy        byte [] sig = new byte[SOCK_SIGNAL_SIZE];
6443b147b770269173d5d711d6c33f142dc5e723824zzy        int ret = readAll(is, sig);
645238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if (VDBG) Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE +
646238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                " bytes signal ret: " + ret);
6473b147b770269173d5d711d6c33f142dc5e723824zzy        ByteBuffer bb = ByteBuffer.wrap(sig);
648238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        /* the struct in native is decorated with __attribute__((packed)), hence this is possible */
6493b147b770269173d5d711d6c33f142dc5e723824zzy        bb.order(ByteOrder.nativeOrder());
6503b147b770269173d5d711d6c33f142dc5e723824zzy        int size = bb.getShort();
651652678af4d18b9a6c18ce6a860de01d958bc82fezzy        if(size != SOCK_SIGNAL_SIZE)
652652678af4d18b9a6c18ce6a860de01d958bc82fezzy            throw new IOException("Connection failure, wrong signal size: " + size);
6533b147b770269173d5d711d6c33f142dc5e723824zzy        byte [] addr = new byte[6];
6543b147b770269173d5d711d6c33f142dc5e723824zzy        bb.get(addr);
6553b147b770269173d5d711d6c33f142dc5e723824zzy        int channel = bb.getInt();
6563b147b770269173d5d711d6c33f142dc5e723824zzy        int status = bb.getInt();
657238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mMaxTxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
658238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mMaxRxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
6593b147b770269173d5d711d6c33f142dc5e723824zzy        String RemoteAddr = convertAddr(addr);
660563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: "
661238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                + RemoteAddr + ", channel: " + channel + ", status: " + status
662238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                + " MaxRxPktSize: " + mMaxRxPacketSize + " MaxTxPktSize: " + mMaxTxPacketSize);
6633b147b770269173d5d711d6c33f142dc5e723824zzy        if(status != 0)
6643b147b770269173d5d711d6c33f142dc5e723824zzy            throw new IOException("Connection failure, status: " + status);
6653b147b770269173d5d711d6c33f142dc5e723824zzy        return RemoteAddr;
6663b147b770269173d5d711d6c33f142dc5e723824zzy    }
667238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
668238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private void createL2capRxBuffer(){
669238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(mType == TYPE_L2CAP) {
670238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // Allocate the buffer to use for reads.
671238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(VDBG) Log.v(TAG, "  Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize);
672238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]);
673238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining());
674238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mL2capBuffer.limit(0); // Ensure we do a real read at the first read-request
675238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(VDBG) Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" +
676238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    mL2capBuffer.remaining());
677238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
678238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
679238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
6803b147b770269173d5d711d6c33f142dc5e723824zzy    private int readAll(InputStream is, byte[] b) throws IOException {
6813b147b770269173d5d711d6c33f142dc5e723824zzy        int left = b.length;
6823b147b770269173d5d711d6c33f142dc5e723824zzy        while(left > 0) {
6833b147b770269173d5d711d6c33f142dc5e723824zzy            int ret = is.read(b, b.length - left, left);
684d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc            if(ret <= 0)
685238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                 throw new IOException("read failed, socket might closed or timeout, read ret: "
686238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                         + ret);
6873b147b770269173d5d711d6c33f142dc5e723824zzy            left -= ret;
6883b147b770269173d5d711d6c33f142dc5e723824zzy            if(left != 0)
6893b147b770269173d5d711d6c33f142dc5e723824zzy                Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) +
6903b147b770269173d5d711d6c33f142dc5e723824zzy                            ", expect size: " + b.length);
69116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
6923b147b770269173d5d711d6c33f142dc5e723824zzy        return b.length;
6933b147b770269173d5d711d6c33f142dc5e723824zzy    }
6943b147b770269173d5d711d6c33f142dc5e723824zzy
6953b147b770269173d5d711d6c33f142dc5e723824zzy    private int readInt(InputStream is) throws IOException {
6963b147b770269173d5d711d6c33f142dc5e723824zzy        byte[] ibytes = new byte[4];
6973b147b770269173d5d711d6c33f142dc5e723824zzy        int ret = readAll(is, ibytes);
698563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) Log.d(TAG, "inputStream.read ret: " + ret);
6993b147b770269173d5d711d6c33f142dc5e723824zzy        ByteBuffer bb = ByteBuffer.wrap(ibytes);
7003b147b770269173d5d711d6c33f142dc5e723824zzy        bb.order(ByteOrder.nativeOrder());
7013b147b770269173d5d711d6c33f142dc5e723824zzy        return bb.getInt();
70216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    }
703238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
704238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private int fillL2capRxBuffer() throws IOException {
705238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mL2capBuffer.rewind();
706238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        int ret = mSocketIS.read(mL2capBuffer.array());
707238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(ret == -1) {
708238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // reached end of stream - return -1
709238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mL2capBuffer.limit(0);
710238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            return -1;
711238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
712238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mL2capBuffer.limit(ret);
713238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        return ret;
714238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
715238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
716238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
7170b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly}
718