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