Merge change 23646 into eclair
* changes: Immediately destroy BluetoothSocket's on close().
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void closeNative(JNIEnv *env, jobject obj) {
|
||||
static void abortNative(JNIEnv *env, jobject obj) {
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
LOGV(__FUNCTION__);
|
||||
struct asocket *s = get_socketData(env, obj);
|
||||
@@ -510,7 +510,7 @@ static JNINativeMethod sMethods[] = {
|
||||
{"availableNative", "()I", (void *) availableNative},
|
||||
{"readNative", "([BII)I", (void *) readNative},
|
||||
{"writeNative", "([BII)I", (void *) writeNative},
|
||||
{"closeNative", "()V", (void *) closeNative},
|
||||
{"abortNative", "()V", (void *) abortNative},
|
||||
{"destroyNative", "()V", (void *) destroyNative},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user