BluetoothSocket.java revision 6a669fac385b51b8bb01844b77a9a43840dda854
10b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly/* 20b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Copyright (C) 2009 The Android Open Source Project 30b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * 40b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 50b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * you may not use this file except in compliance with the License. 60b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * You may obtain a copy of the License at 70b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * 80b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 90b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * 100b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Unless required by applicable law or agreed to in writing, software 110b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 120b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * See the License for the specific language governing permissions and 140b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * limitations under the License. 150b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 160b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 170b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellypackage android.bluetooth; 180b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 190b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.Closeable; 200b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.IOException; 210b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.InputStream; 220b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellyimport java.io.OutputStream; 230b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 240b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly/** 250b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Represents a connected or connecting Bluetooth Socket. 260b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * 270b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Currently only supports RFCOMM sockets. 280b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * 290b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * RFCOMM is a connection orientated, streaming transport over Bluetooth. It is 300b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * also known as the Serial Port Profile (SPP). 310b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * 326a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly * TODO: Consider exposing L2CAP sockets. 330b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * TODO: Clean up javadoc grammer and formatting. 340b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * TODO: Remove @hide 350b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @hide 360b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 370b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pellypublic final class BluetoothSocket implements Closeable { 386a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /** Keep TYPE_RFCOMM etc in sync with BluetoothSocket.cpp */ 396a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ static final int TYPE_RFCOMM = 1; 406a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ static final int TYPE_SCO = 2; 416a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ static final int TYPE_L2CAP = 3; 426a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly 436a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly private final int mType; /* one of TYPE_RFCOMM etc */ 446a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly private final int mPort; /* RFCOMM channel or L2CAP psm */ 450b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly private final String mAddress; /* remote address */ 460b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly private final boolean mAuth; 470b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly private final boolean mEncrypt; 480b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly private final BluetoothInputStream mInputStream; 490b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly private final BluetoothOutputStream mOutputStream; 500b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 510b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly private int mSocketData; /* used by native code only */ 520b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 530b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /** 540b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Construct a secure RFCOMM socket ready to start an outgoing connection. 550b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Call #connect on the returned #BluetoothSocket to begin the connection. 560b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * The remote device will be authenticated and communication on this socket 570b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * will be encrypted. 580b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param address remote Bluetooth address that this socket can connect to 590b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param port remote port 600b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @return an RFCOMM BluetoothSocket 610b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @throws IOException on error, for example Bluetooth not available, or 620b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * insufficient permissions. 630b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 640b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly public static BluetoothSocket createRfcommSocket(String address, int port) 650b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly throws IOException { 666a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly return new BluetoothSocket(TYPE_RFCOMM, -1, true, true, address, port); 670b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 680b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 690b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /** 700b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Construct an insecure RFCOMM socket ready to start an outgoing 710b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * connection. 720b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Call #connect on the returned #BluetoothSocket to begin the connection. 730b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * The remote device will not be authenticated and communication on this 740b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * socket will not be encrypted. 750b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param address remote Bluetooth address that this socket can connect to 760b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param port remote port 770b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @return An RFCOMM BluetoothSocket 780b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @throws IOException On error, for example Bluetooth not available, or 790b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * insufficient permissions. 800b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 810b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly public static BluetoothSocket createInsecureRfcommSocket(String address, int port) 820b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly throws IOException { 836a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly return new BluetoothSocket(TYPE_RFCOMM, -1, false, false, address, port); 846a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly } 856a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly 866a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /** 876a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly * Construct a SCO socket ready to start an outgoing connection. 886a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly * Call #connect on the returned #BluetoothSocket to begin the connection. 896a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly * @param address remote Bluetooth address that this socket can connect to 906a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly * @return a SCO BluetoothSocket 916a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly * @throws IOException on error, for example Bluetooth not available, or 926a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly * insufficient permissions. 936a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly */ 946a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly public static BluetoothSocket createScoSocket(String address, int port) 956a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly throws IOException { 966a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly return new BluetoothSocket(TYPE_SCO, -1, true, true, address, port); 970b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 980b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 990b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /** 1000b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Construct a Bluetooth. 1016a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly * @param type type of socket 1020b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param fd fd to use for connected socket, or -1 for a new socket 1030b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param auth require the remote device to be authenticated 1040b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param encrypt require the connection to be encrypted 1050b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param address remote Bluetooth address that this socket can connect to 1060b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @param port remote port 1070b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @throws IOException On error, for example Bluetooth not available, or 1080b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * insufficient priveleges 1090b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 1106a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, 1116a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly int port) throws IOException { 1126a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly mType = type; 1130b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly mAuth = auth; 1140b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly mEncrypt = encrypt; 1150b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly mAddress = address; 1160b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly mPort = port; 1170b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly if (fd == -1) { 1180b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly initSocketNative(); 1190b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } else { 1200b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly initSocketFromFdNative(fd); 1210b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1220b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly mInputStream = new BluetoothInputStream(this); 1230b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly mOutputStream = new BluetoothOutputStream(this); 1240b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1250b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 1260b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly @Override 1270b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly protected void finalize() throws Throwable { 1280b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly try { 1290b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly close(); 1300b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } finally { 1310b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly super.finalize(); 1320b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1330b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1340b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 1350b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /** 1360b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Attempt to connect to a remote device. 1370b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * This method will block until a connection is made or the connection 1380b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * fails. If this method returns without an exception then this socket 1390b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * is now connected. #close can be used to abort this call from another 1400b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * thread. 1410b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @throws IOException On error, for example connection failure 1420b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 1430b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly public void connect() throws IOException { 1446a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly connectNative(); 1450b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1460b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 1470b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /** 1480b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Closes this socket. 1490b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * This will cause other blocking calls on this socket to immediately 1500b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * throw an IOException. 1510b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 1520b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly public void close() throws IOException { 1530b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly closeNative(); 1540b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1550b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 1560b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /** 1570b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Return the address we are connecting, or connected, to. 1580b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @return Bluetooth address, or null if this socket has not yet attempted 1590b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * or established a connection. 1600b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 1610b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly public String getAddress() { 1620b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly return mAddress; 1630b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1640b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 1650b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /** 1660b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Get the input stream associated with this socket. 1670b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * The input stream will be returned even if the socket is not yet 1680b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * connected, but operations on that stream will throw IOException until 1690b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * the associated socket is connected. 1700b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @return InputStream 1710b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 1720b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly public InputStream getInputStream() throws IOException { 1730b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly return mInputStream; 1740b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1750b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 1760b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /** 1770b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * Get the output stream associated with this socket. 1780b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * The output stream will be returned even if the socket is not yet 1790b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * connected, but operations on that stream will throw IOException until 1800b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * the associated socket is connected. 1810b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly * @return OutputStream 1820b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly */ 1830b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly public OutputStream getOutputStream() throws IOException { 1840b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly return mOutputStream; 1850b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly } 1860b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly 1876a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly private native void initSocketNative() throws IOException; 1886a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly private native void initSocketFromFdNative(int fd) throws IOException; 1896a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly private native void connectNative() throws IOException; 1906a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ native void bindListenNative() throws IOException; 1910b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly /*package*/ native BluetoothSocket acceptNative(int timeout) throws IOException; 1926a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ native int availableNative() throws IOException; 1936a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ native int readNative(byte[] b, int offset, int length) throws IOException; 1946a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ native int writeNative(byte[] b, int offset, int length) throws IOException; 1956a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly /*package*/ native void closeNative() throws IOException; 1966a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly private native void destroyNative() throws IOException; 1970b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly} 198