BluetoothSocket.java revision bd022f423a33f0794bb53e5b0720da2d67e4631c
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 */
45bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private final BluetoothDevice mDevice;    /* remote device */
460b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final String mAddress;    /* remote address */
470b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final boolean mAuth;
480b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final boolean mEncrypt;
490b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final BluetoothInputStream mInputStream;
500b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private final BluetoothOutputStream mOutputStream;
510b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
520b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    private int mSocketData;    /* used by native code only */
530b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
540b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
55bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Construct a BluetoothSocket.
566a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly     * @param type    type of socket
570b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @param fd      fd to use for connected socket, or -1 for a new socket
580b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @param auth    require the remote device to be authenticated
590b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @param encrypt require the connection to be encrypted
60bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param device  remote device that this socket can connect to
610b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @param port    remote port
620b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @throws IOException On error, for example Bluetooth not available, or
630b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     *                     insufficient priveleges
640b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
65bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
66bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            BluetoothDevice device, int port) throws IOException {
676a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly        mType = type;
680b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mAuth = auth;
690b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mEncrypt = encrypt;
70bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mDevice = device;
71bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        if (device == null) {
72bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            mAddress = null;
73bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        } else {
74bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            mAddress = device.getAddress();
75bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        }
760b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mPort = port;
770b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        if (fd == -1) {
780b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly            initSocketNative();
790b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        } else {
800b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly            initSocketFromFdNative(fd);
810b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        }
820b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mInputStream = new BluetoothInputStream(this);
830b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        mOutputStream = new BluetoothOutputStream(this);
840b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
850b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
86bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /**
87bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Construct a BluetoothSocket from address.
88bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param type    type of socket
89bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param fd      fd to use for connected socket, or -1 for a new socket
90bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param auth    require the remote device to be authenticated
91bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param encrypt require the connection to be encrypted
92bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param address remote device that this socket can connect to
93bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @param port    remote port
94bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @throws IOException On error, for example Bluetooth not available, or
95bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     *                     insufficient priveleges
96bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     */
97bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address,
98bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            int port) throws IOException {
99bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        this(type, fd, auth, encrypt, new BluetoothDevice(address), port);
100bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    }
101bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly
1020b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    @Override
1030b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    protected void finalize() throws Throwable {
1040b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        try {
1050b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly            close();
1060b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        } finally {
1070b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly            super.finalize();
1080b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        }
1090b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1100b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1110b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
1120b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Attempt to connect to a remote device.
1130b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * This method will block until a connection is made or the connection
1140b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * fails. If this method returns without an exception then this socket
1150b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * is now connected. #close can be used to abort this call from another
1160b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * thread.
1170b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @throws IOException On error, for example connection failure
1180b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
1190b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public void connect() throws IOException {
1206a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly        connectNative();
1210b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1220b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1230b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
1240b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Closes this socket.
1250b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * This will cause other blocking calls on this socket to immediately
1260b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * throw an IOException.
1270b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
1280b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public void close() throws IOException {
1290b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        closeNative();
1300b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1310b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1320b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
133bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Return the remote device we are connecting, or connected, to.
134bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @return remote device, or null if this socket has not yet attempted
1350b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     *         or established a connection.
1360b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
137bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public BluetoothDevice getRemoteDevice() {
138bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        return mDevice;
1390b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1400b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1410b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
1420b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Get the input stream associated with this socket.
1430b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * The input stream will be returned even if the socket is not yet
1440b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * connected, but operations on that stream will throw IOException until
1450b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * the associated socket is connected.
1460b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @return InputStream
1470b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
1480b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public InputStream getInputStream() throws IOException {
1490b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        return mInputStream;
1500b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1510b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1520b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /**
1530b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * Get the output stream associated with this socket.
1540b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * The output stream will be returned even if the socket is not yet
1550b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * connected, but operations on that stream will throw IOException until
1560b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * the associated socket is connected.
1570b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     * @return OutputStream
1580b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly     */
1590b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    public OutputStream getOutputStream() throws IOException {
1600b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly        return mOutputStream;
1610b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    }
1620b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly
1636a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    private native void initSocketNative() throws IOException;
1646a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    private native void initSocketFromFdNative(int fd) throws IOException;
1656a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    private native void connectNative() throws IOException;
1666a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    /*package*/ native void bindListenNative() throws IOException;
1670b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly    /*package*/ native BluetoothSocket acceptNative(int timeout) throws IOException;
1686a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    /*package*/ native int availableNative() throws IOException;
1696a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    /*package*/ native int readNative(byte[] b, int offset, int length) throws IOException;
1706a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    /*package*/ native int writeNative(byte[] b, int offset, int length) throws IOException;
1716a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    /*package*/ native void closeNative() throws IOException;
1726a669fac385b51b8bb01844b77a9a43840dda854Nick Pelly    private native void destroyNative() throws IOException;
1730b6955a48bad9aee01ae2f0c06d3f168ca603ab7Nick Pelly}
174