diff options
Diffstat (limited to 'core/java/android/bluetooth')
5 files changed, 104 insertions, 19 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 6bd2a5a..8975fe2 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -312,7 +312,7 @@ public final class BluetoothAdapter { BluetoothServerSocket socket = new BluetoothServerSocket( BluetoothSocket.TYPE_RFCOMM, true, true, channel); try { - socket.mSocket.bindListenNative(); + socket.mSocket.bindListen(); } catch (IOException e) { try { socket.close(); @@ -334,7 +334,7 @@ public final class BluetoothAdapter { BluetoothServerSocket socket = new BluetoothServerSocket( BluetoothSocket.TYPE_RFCOMM, false, false, port); try { - socket.mSocket.bindListenNative(); + socket.mSocket.bindListen(); } catch (IOException e) { try { socket.close(); @@ -356,7 +356,7 @@ public final class BluetoothAdapter { BluetoothServerSocket socket = new BluetoothServerSocket( BluetoothSocket.TYPE_SCO, false, false, -1); try { - socket.mSocket.bindListenNative(); + socket.mSocket.bindListen(); } catch (IOException e) { try { socket.close(); diff --git a/core/java/android/bluetooth/BluetoothInputStream.java b/core/java/android/bluetooth/BluetoothInputStream.java index c060f32..03af953 100644 --- a/core/java/android/bluetooth/BluetoothInputStream.java +++ b/core/java/android/bluetooth/BluetoothInputStream.java @@ -37,7 +37,7 @@ import java.io.InputStream; * Return number of bytes available before this stream will block. */ public int available() throws IOException { - return mSocket.availableNative(); + return mSocket.available(); } public void close() throws IOException { @@ -57,7 +57,7 @@ import java.io.InputStream; */ public int read() throws IOException { byte b[] = new byte[1]; - int ret = mSocket.readNative(b, 0, 1); + int ret = mSocket.read(b, 0, 1); if (ret == 1) { return (int)b[0] & 0xff; } else { @@ -93,6 +93,6 @@ import java.io.InputStream; if ((offset | length) < 0 || length > b.length - offset) { throw new ArrayIndexOutOfBoundsException("invalid offset or length"); } - return mSocket.readNative(b, offset, length); + return mSocket.read(b, offset, length); } } diff --git a/core/java/android/bluetooth/BluetoothOutputStream.java b/core/java/android/bluetooth/BluetoothOutputStream.java index 7e2ead4..62242a2 100644 --- a/core/java/android/bluetooth/BluetoothOutputStream.java +++ b/core/java/android/bluetooth/BluetoothOutputStream.java @@ -53,7 +53,7 @@ import java.io.OutputStream; public void write(int oneByte) throws IOException { byte b[] = new byte[1]; b[0] = (byte)oneByte; - mSocket.writeNative(b, 0, 1); + mSocket.write(b, 0, 1); } /** @@ -82,6 +82,6 @@ import java.io.OutputStream; if ((offset | count) < 0 || count > b.length - offset) { throw new IndexOutOfBoundsException("invalid offset or length"); } - mSocket.writeNative(b, offset, count); + mSocket.write(b, offset, count); } } diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java index e653c23..b650841 100644 --- a/core/java/android/bluetooth/BluetoothServerSocket.java +++ b/core/java/android/bluetooth/BluetoothServerSocket.java @@ -47,6 +47,7 @@ import java.io.IOException; * operations and close the socket. */ public final class BluetoothServerSocket implements Closeable { + /*package*/ final BluetoothSocket mSocket; /** @@ -88,7 +89,7 @@ public final class BluetoothServerSocket implements Closeable { * timeout */ public BluetoothSocket accept(int timeout) throws IOException { - return mSocket.acceptNative(timeout); + return mSocket.accept(timeout); } /** @@ -97,6 +98,6 @@ public final class BluetoothServerSocket implements Closeable { * throw an IOException. */ public void close() throws IOException { - mSocket.closeNative(); + mSocket.close(); } } diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index eae0f37..ccbe23e 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -21,6 +21,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.concurrent.locks.ReentrantReadWriteLock; + /** * A connected or connecting Bluetooth socket. * @@ -63,7 +65,14 @@ public final class BluetoothSocket implements Closeable { private final BluetoothInputStream mInputStream; private final BluetoothOutputStream mOutputStream; - private int mSocketData; /* used by native code only */ + /** prevents all native calls after destroyNative() */ + private boolean mClosed; + + /** protects mClosed */ + private final ReentrantReadWriteLock mLock; + + /** used by native code only */ + private int mSocketData; /** * Construct a BluetoothSocket. @@ -95,6 +104,8 @@ public final class BluetoothSocket implements Closeable { } mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); + mClosed = false; + mLock = new ReentrantReadWriteLock(); } /** @@ -132,7 +143,13 @@ public final class BluetoothSocket implements Closeable { * @throws IOException on error, for example connection failure */ public void connect() throws IOException { - connectNative(); + mLock.readLock().lock(); + try { + if (mClosed) throw new IOException("socket closed"); + connectNative(); + } finally { + mLock.readLock().unlock(); + } } /** @@ -141,7 +158,24 @@ public final class BluetoothSocket implements Closeable { * throw an IOException. */ public void close() throws IOException { - closeNative(); + // abort blocking operations on the socket + mLock.readLock().lock(); + try { + if (mClosed) return; + abortNative(); + } finally { + mLock.readLock().unlock(); + } + + // all native calls are guarenteed to immediately return after + // abortNative(), so this lock should immediatley acquire + mLock.writeLock().lock(); + try { + mClosed = true; + destroyNative(); + } finally { + mLock.writeLock().unlock(); + } } /** @@ -174,14 +208,64 @@ public final class BluetoothSocket implements Closeable { return mOutputStream; } + /*package*/ void bindListen() throws IOException { + mLock.readLock().lock(); + try { + if (mClosed) throw new IOException("socket closed"); + bindListenNative(); + } finally { + mLock.readLock().unlock(); + } + } + + /*package*/ BluetoothSocket accept(int timeout) throws IOException { + mLock.readLock().lock(); + try { + if (mClosed) throw new IOException("socket closed"); + return acceptNative(timeout); + } finally { + mLock.readLock().unlock(); + } + } + + /*package*/ int available() throws IOException { + mLock.readLock().lock(); + try { + if (mClosed) throw new IOException("socket closed"); + return availableNative(); + } finally { + mLock.readLock().unlock(); + } + } + + /*package*/ int read(byte[] b, int offset, int length) throws IOException { + mLock.readLock().lock(); + try { + if (mClosed) throw new IOException("socket closed"); + return readNative(b, offset, length); + } finally { + mLock.readLock().unlock(); + } + } + + /*package*/ int write(byte[] b, int offset, int length) throws IOException { + mLock.readLock().lock(); + try { + if (mClosed) throw new IOException("socket closed"); + return writeNative(b, offset, length); + } finally { + mLock.readLock().unlock(); + } + } + private native void initSocketNative() throws IOException; private native void initSocketFromFdNative(int fd) throws IOException; private native void connectNative() throws IOException; - /*package*/ native void bindListenNative() throws IOException; - /*package*/ native BluetoothSocket acceptNative(int timeout) throws IOException; - /*package*/ native int availableNative() throws IOException; - /*package*/ native int readNative(byte[] b, int offset, int length) throws IOException; - /*package*/ native int writeNative(byte[] b, int offset, int length) throws IOException; - /*package*/ native void closeNative() throws IOException; + private native void bindListenNative() throws IOException; + private native BluetoothSocket acceptNative(int timeout) throws IOException; + private native int availableNative() throws IOException; + private native int readNative(byte[] b, int offset, int length) throws IOException; + private native int writeNative(byte[] b, int offset, int length) throws IOException; + private native void abortNative() throws IOException; private native void destroyNative() throws IOException; } |
