Merge change 23646 into eclair

* changes:
  Immediately destroy BluetoothSocket's on close().
This commit is contained in:
Android (Google) Code Review
2009-09-02 16:01:15 -07:00
6 changed files with 106 additions and 21 deletions

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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},
};