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