From 53f441bf8d89667e099302d506c6f07ed1201db1 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Tue, 26 May 2009 19:13:43 -0700 Subject: New BluetoothSocket API. Modeled on blocking java.net.Socket and java.net.ServerSocket library. Public interface is: public final class BluetoothSocket implements Closeable { public static BluetoothSocket createRfcommSocket(String address, int port) throws IOException; public static BluetoothSocket createInsecureRfcommSocket(String address, int port) throws IOException; public void connect() throws IOException; public void close() throws IOException; public String getAddress(); public InputStream getInputStream() throws IOException; public OutputStream getOutputStream() throws IOException; } public final class BluetoothServerSocket implements Closeable { public static BluetoothServerSocket listenUsingRfcommOn(int port) throws IOException; public static BluetoothServerSocket listenUsingUnsecureRfcommOn(int port) throws IOException; public BluetoothSocket accept() throws IOException; public BluetoothSocket accept(int timeout) throws IOException; public void close() throws IOException; } --- .../java/android/bluetooth/BluetoothSocket.java | 176 +++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 framework/java/android/bluetooth/BluetoothSocket.java (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java new file mode 100644 index 0000000000..fd8885ece9 --- /dev/null +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Represents a connected or connecting Bluetooth Socket. + * + * Currently only supports RFCOMM sockets. + * + * RFCOMM is a connection orientated, streaming transport over Bluetooth. It is + * also known as the Serial Port Profile (SPP). + * + * TODO: Consider implementing SCO and L2CAP sockets. + * TODO: Clean up javadoc grammer and formatting. + * TODO: Remove @hide + * @hide + */ +public final class BluetoothSocket implements Closeable { + private final int mPort; + private final String mAddress; /* remote address */ + private final boolean mAuth; + private final boolean mEncrypt; + private final BluetoothInputStream mInputStream; + private final BluetoothOutputStream mOutputStream; + + private int mSocketData; /* used by native code only */ + + /** + * Construct a secure RFCOMM socket ready to start an outgoing connection. + * Call #connect on the returned #BluetoothSocket to begin the connection. + * The remote device will be authenticated and communication on this socket + * will be encrypted. + * @param address remote Bluetooth address that this socket can connect to + * @param port remote port + * @return an RFCOMM BluetoothSocket + * @throws IOException on error, for example Bluetooth not available, or + * insufficient permissions. + */ + public static BluetoothSocket createRfcommSocket(String address, int port) + throws IOException { + return new BluetoothSocket(-1, true, true, address, port); + } + + /** + * Construct an insecure RFCOMM socket ready to start an outgoing + * connection. + * Call #connect on the returned #BluetoothSocket to begin the connection. + * The remote device will not be authenticated and communication on this + * socket will not be encrypted. + * @param address remote Bluetooth address that this socket can connect to + * @param port remote port + * @return An RFCOMM BluetoothSocket + * @throws IOException On error, for example Bluetooth not available, or + * insufficient permissions. + */ + public static BluetoothSocket createInsecureRfcommSocket(String address, int port) + throws IOException { + return new BluetoothSocket(-1, false, false, address, port); + } + + /** + * Construct a Bluetooth. + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated + * @param encrypt require the connection to be encrypted + * @param address remote Bluetooth address that this socket can connect to + * @param port remote port + * @throws IOException On error, for example Bluetooth not available, or + * insufficient priveleges + */ + /*package*/ BluetoothSocket(int fd, boolean auth, boolean encrypt, String address, int port) + throws IOException { + mAuth = auth; + mEncrypt = encrypt; + mAddress = address; + mPort = port; + if (fd == -1) { + initSocketNative(); + } else { + initSocketFromFdNative(fd); + } + mInputStream = new BluetoothInputStream(this); + mOutputStream = new BluetoothOutputStream(this); + } + + @Override + protected void finalize() throws Throwable { + try { + close(); + } finally { + super.finalize(); + } + } + + /** + * Attempt to connect to a remote device. + * This method will block until a connection is made or the connection + * fails. If this method returns without an exception then this socket + * is now connected. #close can be used to abort this call from another + * thread. + * @throws IOException On error, for example connection failure + */ + public void connect() throws IOException { + connectNative(mAddress, mPort, -1); + } + + /** + * Closes this socket. + * This will cause other blocking calls on this socket to immediately + * throw an IOException. + */ + public void close() throws IOException { + closeNative(); + } + + /** + * Return the address we are connecting, or connected, to. + * @return Bluetooth address, or null if this socket has not yet attempted + * or established a connection. + */ + public String getAddress() { + return mAddress; + } + + /** + * Get the input stream associated with this socket. + * The input stream will be returned even if the socket is not yet + * connected, but operations on that stream will throw IOException until + * the associated socket is connected. + * @return InputStream + */ + public InputStream getInputStream() throws IOException { + return mInputStream; + } + + /** + * Get the output stream associated with this socket. + * The output stream will be returned even if the socket is not yet + * connected, but operations on that stream will throw IOException until + * the associated socket is connected. + * @return OutputStream + */ + public OutputStream getOutputStream() throws IOException { + return mOutputStream; + } + + private native void initSocketNative(); + private native void initSocketFromFdNative(int fd); + private native void connectNative(String address, int port, int timeout); + /*package*/ native void bindListenNative(int port) throws IOException; + /*package*/ native BluetoothSocket acceptNative(int timeout) throws IOException; + /*package*/ native int availableNative(); + /*package*/ native int readNative(); + /*package*/ native void writeNative(int data); + /*package*/ native void closeNative(); + private native void destroyNative(); +} -- cgit v1.2.3 From 731bcb12e10d3527cf6c15d5e0da6161482787c0 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Mon, 1 Jun 2009 19:09:37 -0700 Subject: Implement bulk read and writes for Bluetooth sockets. Before: 0.1 kB/s After: 100 kB/s (in my java BT speed test app) --- framework/java/android/bluetooth/BluetoothSocket.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index fd8885ece9..670146b245 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -169,8 +169,8 @@ public final class BluetoothSocket implements Closeable { /*package*/ native void bindListenNative(int port) throws IOException; /*package*/ native BluetoothSocket acceptNative(int timeout) throws IOException; /*package*/ native int availableNative(); - /*package*/ native int readNative(); - /*package*/ native void writeNative(int data); + /*package*/ native int readNative(byte[] b, int offset, int length); + /*package*/ native int writeNative(byte[] b, int offset, int length); /*package*/ native void closeNative(); private native void destroyNative(); } -- cgit v1.2.3 From cb32d7c30a5ae45bc6e8a81ae59b1e75bdff0c74 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Tue, 2 Jun 2009 15:57:18 -0700 Subject: Implement and expose SCO socket support in BluetoothSocket.java. Implement L2CAP socket support, but do not expose it (untested). NEXT: Switch to Builder style constructor instead of factory method. --- .../java/android/bluetooth/BluetoothSocket.java | 53 +++++++++++++++------- 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 670146b245..de1f32601d 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -29,13 +29,19 @@ import java.io.OutputStream; * RFCOMM is a connection orientated, streaming transport over Bluetooth. It is * also known as the Serial Port Profile (SPP). * - * TODO: Consider implementing SCO and L2CAP sockets. + * TODO: Consider exposing L2CAP sockets. * TODO: Clean up javadoc grammer and formatting. * TODO: Remove @hide * @hide */ public final class BluetoothSocket implements Closeable { - private final int mPort; + /** Keep TYPE_RFCOMM etc in sync with BluetoothSocket.cpp */ + /*package*/ static final int TYPE_RFCOMM = 1; + /*package*/ static final int TYPE_SCO = 2; + /*package*/ static final int TYPE_L2CAP = 3; + + private final int mType; /* one of TYPE_RFCOMM etc */ + private final int mPort; /* RFCOMM channel or L2CAP psm */ private final String mAddress; /* remote address */ private final boolean mAuth; private final boolean mEncrypt; @@ -57,7 +63,7 @@ public final class BluetoothSocket implements Closeable { */ public static BluetoothSocket createRfcommSocket(String address, int port) throws IOException { - return new BluetoothSocket(-1, true, true, address, port); + return new BluetoothSocket(TYPE_RFCOMM, -1, true, true, address, port); } /** @@ -74,11 +80,25 @@ public final class BluetoothSocket implements Closeable { */ public static BluetoothSocket createInsecureRfcommSocket(String address, int port) throws IOException { - return new BluetoothSocket(-1, false, false, address, port); + return new BluetoothSocket(TYPE_RFCOMM, -1, false, false, address, port); + } + + /** + * Construct a SCO socket ready to start an outgoing connection. + * Call #connect on the returned #BluetoothSocket to begin the connection. + * @param address remote Bluetooth address that this socket can connect to + * @return a SCO BluetoothSocket + * @throws IOException on error, for example Bluetooth not available, or + * insufficient permissions. + */ + public static BluetoothSocket createScoSocket(String address, int port) + throws IOException { + return new BluetoothSocket(TYPE_SCO, -1, true, true, address, port); } /** * Construct a Bluetooth. + * @param type type of socket * @param fd fd to use for connected socket, or -1 for a new socket * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted @@ -87,8 +107,9 @@ public final class BluetoothSocket implements Closeable { * @throws IOException On error, for example Bluetooth not available, or * insufficient priveleges */ - /*package*/ BluetoothSocket(int fd, boolean auth, boolean encrypt, String address, int port) - throws IOException { + /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, + int port) throws IOException { + mType = type; mAuth = auth; mEncrypt = encrypt; mAddress = address; @@ -120,7 +141,7 @@ public final class BluetoothSocket implements Closeable { * @throws IOException On error, for example connection failure */ public void connect() throws IOException { - connectNative(mAddress, mPort, -1); + connectNative(); } /** @@ -163,14 +184,14 @@ public final class BluetoothSocket implements Closeable { return mOutputStream; } - private native void initSocketNative(); - private native void initSocketFromFdNative(int fd); - private native void connectNative(String address, int port, int timeout); - /*package*/ native void bindListenNative(int port) throws IOException; + 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(); - /*package*/ native int readNative(byte[] b, int offset, int length); - /*package*/ native int writeNative(byte[] b, int offset, int length); - /*package*/ native void closeNative(); - private native void destroyNative(); + /*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 destroyNative() throws IOException; } -- cgit v1.2.3 From 2d66488e7d7aeb87e4f7385dfe1a6c800c08391b Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Fri, 14 Aug 2009 18:33:38 -0700 Subject: Bluetooth: API change. Split BluetoothDevice into BluetoothDevice and BluetoothAdapter. BluetoothAdapter: Represents the local BT adapter. Operations on the local adapter (start a scan, etc). BluetoothDevice: Represents a remote BT device. Operations on remote devices (pair, connect, etc). IBluetoothDevice.aidl -> Bluetooth.aidl BluetoothDeviceService.java -> BluetoothDeviceService.java TODO: Javadoc --- .../java/android/bluetooth/BluetoothSocket.java | 86 ++++++++-------------- 1 file changed, 31 insertions(+), 55 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index de1f32601d..dda2cef99e 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -42,6 +42,7 @@ public final class BluetoothSocket implements Closeable { private final int mType; /* one of TYPE_RFCOMM etc */ private final int mPort; /* RFCOMM channel or L2CAP psm */ + private final BluetoothDevice mDevice; /* remote device */ private final String mAddress; /* remote address */ private final boolean mAuth; private final boolean mEncrypt; @@ -51,68 +52,27 @@ public final class BluetoothSocket implements Closeable { private int mSocketData; /* used by native code only */ /** - * Construct a secure RFCOMM socket ready to start an outgoing connection. - * Call #connect on the returned #BluetoothSocket to begin the connection. - * The remote device will be authenticated and communication on this socket - * will be encrypted. - * @param address remote Bluetooth address that this socket can connect to - * @param port remote port - * @return an RFCOMM BluetoothSocket - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions. - */ - public static BluetoothSocket createRfcommSocket(String address, int port) - throws IOException { - return new BluetoothSocket(TYPE_RFCOMM, -1, true, true, address, port); - } - - /** - * Construct an insecure RFCOMM socket ready to start an outgoing - * connection. - * Call #connect on the returned #BluetoothSocket to begin the connection. - * The remote device will not be authenticated and communication on this - * socket will not be encrypted. - * @param address remote Bluetooth address that this socket can connect to - * @param port remote port - * @return An RFCOMM BluetoothSocket - * @throws IOException On error, for example Bluetooth not available, or - * insufficient permissions. - */ - public static BluetoothSocket createInsecureRfcommSocket(String address, int port) - throws IOException { - return new BluetoothSocket(TYPE_RFCOMM, -1, false, false, address, port); - } - - /** - * Construct a SCO socket ready to start an outgoing connection. - * Call #connect on the returned #BluetoothSocket to begin the connection. - * @param address remote Bluetooth address that this socket can connect to - * @return a SCO BluetoothSocket - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions. - */ - public static BluetoothSocket createScoSocket(String address, int port) - throws IOException { - return new BluetoothSocket(TYPE_SCO, -1, true, true, address, port); - } - - /** - * Construct a Bluetooth. + * Construct a BluetoothSocket. * @param type type of socket * @param fd fd to use for connected socket, or -1 for a new socket * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param address remote Bluetooth address that this socket can connect to + * @param device remote device that this socket can connect to * @param port remote port * @throws IOException On error, for example Bluetooth not available, or * insufficient priveleges */ - /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, - int port) throws IOException { + /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, + BluetoothDevice device, int port) throws IOException { mType = type; mAuth = auth; mEncrypt = encrypt; - mAddress = address; + mDevice = device; + if (device == null) { + mAddress = null; + } else { + mAddress = device.getAddress(); + } mPort = port; if (fd == -1) { initSocketNative(); @@ -123,6 +83,22 @@ public final class BluetoothSocket implements Closeable { mOutputStream = new BluetoothOutputStream(this); } + /** + * Construct a BluetoothSocket from address. + * @param type type of socket + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated + * @param encrypt require the connection to be encrypted + * @param address remote device that this socket can connect to + * @param port remote port + * @throws IOException On error, for example Bluetooth not available, or + * insufficient priveleges + */ + private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, + int port) throws IOException { + this(type, fd, auth, encrypt, new BluetoothDevice(address), port); + } + @Override protected void finalize() throws Throwable { try { @@ -154,12 +130,12 @@ public final class BluetoothSocket implements Closeable { } /** - * Return the address we are connecting, or connected, to. - * @return Bluetooth address, or null if this socket has not yet attempted + * Return the remote device we are connecting, or connected, to. + * @return remote device, or null if this socket has not yet attempted * or established a connection. */ - public String getAddress() { - return mAddress; + public BluetoothDevice getRemoteDevice() { + return mDevice; } /** -- cgit v1.2.3 From 753da539da89aac6762ef2183680205f8fd4e95a Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Wed, 19 Aug 2009 11:00:00 -0700 Subject: API CHANGE Javadoc, and unhide the first pieces of the Bluetooth API. With this commit there is enough public API to connect and use an RFCOMM connection between Bluetooth devices. --- .../java/android/bluetooth/BluetoothSocket.java | 54 ++++++++++++++-------- 1 file changed, 34 insertions(+), 20 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index dda2cef99e..eae0f3716e 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -22,20 +22,34 @@ import java.io.InputStream; import java.io.OutputStream; /** - * Represents a connected or connecting Bluetooth Socket. + * A connected or connecting Bluetooth socket. * - * Currently only supports RFCOMM sockets. + *

The interface for Bluetooth Sockets is similar to that of TCP sockets: + * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server + * side, use a {@link BluetoothServerSocket} to create a listening server + * socket. It will return a new, connected {@link BluetoothSocket} on an + * accepted connection. On the client side, use the same + * {@link BluetoothSocket} object to both intiate the outgoing connection, + * and to manage the connected socket. * - * RFCOMM is a connection orientated, streaming transport over Bluetooth. It is - * also known as the Serial Port Profile (SPP). + *

The most common type of Bluetooth Socket is RFCOMM. RFCOMM is a + * connection orientated, streaming transport over Bluetooth. It is also known + * as the Serial Port Profile (SPP). * - * TODO: Consider exposing L2CAP sockets. - * TODO: Clean up javadoc grammer and formatting. - * TODO: Remove @hide - * @hide + *

Use {@link BluetoothDevice#createRfcommSocket} to create a new {@link + * BluetoothSocket} ready for an outgoing connection to a remote + * {@link BluetoothDevice}. + * + *

Use {@link BluetoothAdapter#listenUsingRfcommOn} to create a listening + * {@link BluetoothServerSocket} ready for incoming connections to the local + * {@link BluetoothAdapter}. + * + *

{@link BluetoothSocket} and {@link BluetoothServerSocket} are thread + * safe. In particular, {@link #close} will always immediately abort ongoing + * operations and close the socket. */ public final class BluetoothSocket implements Closeable { - /** Keep TYPE_RFCOMM etc in sync with BluetoothSocket.cpp */ + /** Keep TYPE_ fields in sync with BluetoothSocket.cpp */ /*package*/ static final int TYPE_RFCOMM = 1; /*package*/ static final int TYPE_SCO = 2; /*package*/ static final int TYPE_L2CAP = 3; @@ -99,6 +113,7 @@ public final class BluetoothSocket implements Closeable { this(type, fd, auth, encrypt, new BluetoothDevice(address), port); } + /** @hide */ @Override protected void finalize() throws Throwable { try { @@ -110,19 +125,19 @@ public final class BluetoothSocket implements Closeable { /** * Attempt to connect to a remote device. - * This method will block until a connection is made or the connection + *

This method will block until a connection is made or the connection * fails. If this method returns without an exception then this socket - * is now connected. #close can be used to abort this call from another - * thread. - * @throws IOException On error, for example connection failure + * is now connected. + *

{@link #close} can be used to abort this call from another thread. + * @throws IOException on error, for example connection failure */ public void connect() throws IOException { connectNative(); } /** - * Closes this socket. - * This will cause other blocking calls on this socket to immediately + * Immediately close this socket, and release all associated resources. + *

Causes blocked calls on this socket in other threads to immediately * throw an IOException. */ public void close() throws IOException { @@ -130,9 +145,8 @@ public final class BluetoothSocket implements Closeable { } /** - * Return the remote device we are connecting, or connected, to. - * @return remote device, or null if this socket has not yet attempted - * or established a connection. + * Get the remote device this socket is connecting, or connected, to. + * @return remote device */ public BluetoothDevice getRemoteDevice() { return mDevice; @@ -140,7 +154,7 @@ public final class BluetoothSocket implements Closeable { /** * Get the input stream associated with this socket. - * The input stream will be returned even if the socket is not yet + *

The input stream will be returned even if the socket is not yet * connected, but operations on that stream will throw IOException until * the associated socket is connected. * @return InputStream @@ -151,7 +165,7 @@ public final class BluetoothSocket implements Closeable { /** * Get the output stream associated with this socket. - * The output stream will be returned even if the socket is not yet + *

The output stream will be returned even if the socket is not yet * connected, but operations on that stream will throw IOException until * the associated socket is connected. * @return OutputStream -- cgit v1.2.3 From 4cd2cd92746e80798c79161791a4042251ed356a Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Wed, 2 Sep 2009 11:51:35 -0700 Subject: Immediately destroy BluetoothSocket's on close(). Unfortunatley, shutdown() on the underlying fd does not actually stop a listening socket from listening. You need to call close() on the fd to do this. There is no way around it. So this means the Java BluetoothSocket code has to call destroyNative() during BluetoothSocket.close(). Since native methods cannot be called after destroyNative(), add a ReadWrite lock and mClosed field to protect access to native methods. This fixes the "resource busy" error when Bluetooth OPP and Bluetooth PBAP tried to resume listening after turning BT off and then on. --- .../java/android/bluetooth/BluetoothSocket.java | 102 +++++++++++++++++++-- 1 file changed, 93 insertions(+), 9 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index eae0f3716e..ccbe23e55c 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/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; } -- cgit v1.2.3 From ed6f2ce927782e15c662eab48cd95d95e7ef7841 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Tue, 8 Sep 2009 10:12:06 -0700 Subject: Add javadoc to explain which permissions are required for Public BT API's. --- framework/java/android/bluetooth/BluetoothSocket.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index ccbe23e55c..e462ea6383 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -49,6 +49,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; *

{@link BluetoothSocket} and {@link BluetoothServerSocket} are thread * safe. In particular, {@link #close} will always immediately abort ongoing * operations and close the socket. + * + *

All methods on a {@link BluetoothSocket} require + * {@link android.Manifest.permission#BLUETOOTH} */ public final class BluetoothSocket implements Closeable { /** Keep TYPE_ fields in sync with BluetoothSocket.cpp */ -- cgit v1.2.3 From ee1402d8d697be3aa2858ee35e57db8c3e845a12 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Fri, 2 Oct 2009 20:34:18 -0700 Subject: Provide an API for apps to use a dynamic RFCOMM channel and SDP record. Hide listenUsingRfcommOn(int channel) Add listenUsingRfcomm(String name, ParcelUuid uuid) The new API automatically finds a free RFCOMM channel and registers an SDP record with the given uuid and name. The SDP record is automatically removed when the socket is closed, or if the application dies. Apps are prevented from registering SDP records with the uuid of system Bluetooth profiles, such as A2DP, HFP and OPP. Apps are prevented from removing SDP records that they did not create. This is tracked by pid. TODO: Provide an API for the connecting app to look up an SDP record. Bug: 2158900 DrNo: eastham Joke: "What did the dog say to the tree? bark." Change-Id: Ia92f51c34615a7270a403255ad2b8faa98c4a3f5 --- .../java/android/bluetooth/BluetoothSocket.java | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index e462ea6383..573cb3d826 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -54,11 +54,17 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * {@link android.Manifest.permission#BLUETOOTH} */ public final class BluetoothSocket implements Closeable { + /** @hide */ + public static final int MAX_RFCOMM_CHANNEL = 30; + /** Keep TYPE_ fields in sync with BluetoothSocket.cpp */ /*package*/ static final int TYPE_RFCOMM = 1; /*package*/ static final int TYPE_SCO = 2; /*package*/ static final int TYPE_L2CAP = 3; + /*package*/ static final int EBADFD = 77; + /*package*/ static final int EADDRINUSE = 98; + private final int mType; /* one of TYPE_RFCOMM etc */ private final int mPort; /* RFCOMM channel or L2CAP psm */ private final BluetoothDevice mDevice; /* remote device */ @@ -90,6 +96,11 @@ public final class BluetoothSocket implements Closeable { */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port) throws IOException { + if (type == BluetoothSocket.TYPE_RFCOMM) { + if (port < 1 || port > MAX_RFCOMM_CHANNEL) { + throw new IOException("Invalid RFCOMM channel: " + port); + } + } mType = type; mAuth = auth; mEncrypt = encrypt; @@ -211,11 +222,15 @@ public final class BluetoothSocket implements Closeable { return mOutputStream; } - /*package*/ void bindListen() throws IOException { + /** + * Currently returns unix errno instead of throwing IOException, + * so that BluetoothAdapter can check the error code for EADDRINUSE + */ + /*package*/ int bindListen() { mLock.readLock().lock(); try { - if (mClosed) throw new IOException("socket closed"); - bindListenNative(); + if (mClosed) return EBADFD; + return bindListenNative(); } finally { mLock.readLock().unlock(); } @@ -264,11 +279,16 @@ public final class BluetoothSocket implements Closeable { private native void initSocketNative() throws IOException; private native void initSocketFromFdNative(int fd) throws IOException; private native void connectNative() throws IOException; - private native void bindListenNative() throws IOException; + private native int bindListenNative(); 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; + /** + * Throws an IOException for given posix errno. Done natively so we can + * use strerr to convert to string error. + */ + /*package*/ native void throwErrnoNative(int errno) throws IOException; } -- cgit v1.2.3 From 1e79198aafef8cde937694e6fdbd863acf4f7b8a Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Tue, 6 Oct 2009 16:10:02 +0200 Subject: Fix docs builds. --- framework/java/android/bluetooth/BluetoothSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 573cb3d826..b9e33f3bda 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -42,7 +42,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * BluetoothSocket} ready for an outgoing connection to a remote * {@link BluetoothDevice}. * - *

Use {@link BluetoothAdapter#listenUsingRfcommOn} to create a listening + *

Use {@link BluetoothAdapter#listenUsingRfcomm} to create a listening * {@link BluetoothServerSocket} ready for incoming connections to the local * {@link BluetoothAdapter}. * -- cgit v1.2.3 From 07b84cb5bb5283352a27cc0cf651586ed00035a0 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Wed, 7 Oct 2009 07:44:03 +0200 Subject: Encourage developers to connect RFCOMM by UUID instead of Channel. Hide createRfcommSocket(int channel) Add createRfcommSocketWithServiceRecord(UUID uuid) Rename listenUsingRfcomm(String,UUID) -> listenUsingRfcommWithServiceRecord(..) Now we have a complete API for developers to make peer-peer RFCOMM connections with hard-coding the limited (30) RFCOMM channels, instead using SDP lookup of an UUID. This commit addresses two serious bugs: - Do not throw IOException on accepting an incoming RFCOMM connection with BluetoothSocket. This was a regression from commit ee1402d8d697be3a - Workaround failure of bluez to update SDP cache when channel changes by trying to use the same RFCOMM channel on the server every time, instead of picking server channels randomly. This is a pretty ugly workaround, and we are still trying to fix the caching issue - but with this workaround we are at least shippable and apps will work at least until they start colliding on the 30 RFCOMM channels. DrNo: eastham Bug: 2158900 Joke: What did the digital watch say to his mom? "Look mom no hands." Change-Id: Ia4879943b83afac06b6f1a3f2391cf1628afce7d --- .../java/android/bluetooth/BluetoothSocket.java | 109 ++++++++++++++++++--- 1 file changed, 95 insertions(+), 14 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index b9e33f3bda..7e725903b3 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -16,11 +16,15 @@ package android.bluetooth; +import android.bluetooth.IBluetoothCallback; +import android.os.ParcelUuid; +import android.os.RemoteException; +import android.util.Log; + import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; - import java.util.concurrent.locks.ReentrantReadWriteLock; /** @@ -38,13 +42,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * connection orientated, streaming transport over Bluetooth. It is also known * as the Serial Port Profile (SPP). * - *

Use {@link BluetoothDevice#createRfcommSocket} to create a new {@link - * BluetoothSocket} ready for an outgoing connection to a remote + *

Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to create + * a new {@link BluetoothSocket} ready for an outgoing connection to a remote * {@link BluetoothDevice}. * - *

Use {@link BluetoothAdapter#listenUsingRfcomm} to create a listening - * {@link BluetoothServerSocket} ready for incoming connections to the local - * {@link BluetoothAdapter}. + *

Use {@link BluetoothAdapter#listenUsingRfcommWithServiceRecord} to + * create a listening {@link BluetoothServerSocket} ready for incoming + * connections to the local {@link BluetoothAdapter}. * *

{@link BluetoothSocket} and {@link BluetoothServerSocket} are thread * safe. In particular, {@link #close} will always immediately abort ongoing @@ -54,6 +58,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * {@link android.Manifest.permission#BLUETOOTH} */ public final class BluetoothSocket implements Closeable { + private static final String TAG = "BluetoothSocket"; + /** @hide */ public static final int MAX_RFCOMM_CHANNEL = 30; @@ -66,13 +72,15 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int EADDRINUSE = 98; private final int mType; /* one of TYPE_RFCOMM etc */ - private final int mPort; /* RFCOMM channel or L2CAP psm */ private final BluetoothDevice mDevice; /* remote device */ private final String mAddress; /* remote address */ private final boolean mAuth; private final boolean mEncrypt; private final BluetoothInputStream mInputStream; private final BluetoothOutputStream mOutputStream; + private final SdpHelper mSdp; + + private int mPort; /* RFCOMM channel or L2CAP psm */ /** prevents all native calls after destroyNative() */ private boolean mClosed; @@ -91,16 +99,24 @@ public final class BluetoothSocket implements Closeable { * @param encrypt require the connection to be encrypted * @param device remote device that this socket can connect to * @param port remote port + * @param uuid SDP uuid * @throws IOException On error, for example Bluetooth not available, or * insufficient priveleges */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, - BluetoothDevice device, int port) throws IOException { - if (type == BluetoothSocket.TYPE_RFCOMM) { + BluetoothDevice device, int port, ParcelUuid uuid) throws IOException { + if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1) { if (port < 1 || port > MAX_RFCOMM_CHANNEL) { throw new IOException("Invalid RFCOMM channel: " + port); } } + if (uuid == null) { + mPort = port; + mSdp = null; + } else { + mSdp = new SdpHelper(device, uuid); + mPort = -1; + } mType = type; mAuth = auth; mEncrypt = encrypt; @@ -110,7 +126,6 @@ public final class BluetoothSocket implements Closeable { } else { mAddress = device.getAddress(); } - mPort = port; if (fd == -1) { initSocketNative(); } else { @@ -123,7 +138,7 @@ public final class BluetoothSocket implements Closeable { } /** - * Construct a BluetoothSocket from address. + * Construct a BluetoothSocket from address. Used by native code. * @param type type of socket * @param fd fd to use for connected socket, or -1 for a new socket * @param auth require the remote device to be authenticated @@ -135,7 +150,7 @@ public final class BluetoothSocket implements Closeable { */ private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port) throws IOException { - this(type, fd, auth, encrypt, new BluetoothDevice(address), port); + this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null); } /** @hide */ @@ -160,7 +175,12 @@ public final class BluetoothSocket implements Closeable { mLock.readLock().lock(); try { if (mClosed) throw new IOException("socket closed"); - connectNative(); + + if (mSdp != null) { + mPort = mSdp.doSdp(); // blocks + } + + connectNative(); // blocks } finally { mLock.readLock().unlock(); } @@ -176,12 +196,15 @@ public final class BluetoothSocket implements Closeable { mLock.readLock().lock(); try { if (mClosed) return; + if (mSdp != null) { + mSdp.cancel(); + } abortNative(); } finally { mLock.readLock().unlock(); } - // all native calls are guarenteed to immediately return after + // all native calls are guaranteed to immediately return after // abortNative(), so this lock should immediatley acquire mLock.writeLock().lock(); try { @@ -291,4 +314,62 @@ public final class BluetoothSocket implements Closeable { * use strerr to convert to string error. */ /*package*/ native void throwErrnoNative(int errno) throws IOException; + + /** + * Helper to perform blocking SDP lookup. + */ + private static class SdpHelper extends IBluetoothCallback.Stub { + private final IBluetooth service; + private final ParcelUuid uuid; + private final BluetoothDevice device; + private int channel; + private boolean canceled; + public SdpHelper(BluetoothDevice device, ParcelUuid uuid) { + service = BluetoothDevice.getService(); + this.device = device; + this.uuid = uuid; + canceled = false; + } + /** + * Returns the RFCOMM channel for the UUID, or throws IOException + * on failure. + */ + public synchronized int doSdp() throws IOException { + if (canceled) throw new IOException("Service discovery canceled"); + channel = -1; + + boolean inProgress = false; + try { + inProgress = service.fetchRemoteUuids(device.getAddress(), uuid, this); + } catch (RemoteException e) {Log.e(TAG, "", e);} + + if (!inProgress) throw new IOException("Unable to start Service Discovery"); + + try { + /* 12 second timeout as a precaution - onRfcommChannelFound + * should always occur before the timeout */ + wait(12000); // block + + } catch (InterruptedException e) {} + + if (canceled) throw new IOException("Service discovery canceled"); + if (channel < 1) throw new IOException("Service discovery failed"); + + return channel; + } + /** Object cannot be re-used after calling cancel() */ + public synchronized void cancel() { + if (!canceled) { + canceled = true; + channel = -1; + notifyAll(); // unblock + } + } + public synchronized void onRfcommChannelFound(int channel) { + if (!canceled) { + this.channel = channel; + notifyAll(); // unblock + } + } + } } -- cgit v1.2.3 From beef809fa89a5e7955a4c25cf70e00adbcf2e24e Mon Sep 17 00:00:00 2001 From: Scott Main Date: Tue, 3 Nov 2009 18:17:59 -0800 Subject: docs: add more documentation for the bluetooth apis. more descriptions for some of the classes and a new overview and pseudo-code example for using BT APIs in the package summary. --- .../java/android/bluetooth/BluetoothSocket.java | 44 ++++++++++++++-------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 7e725903b3..dbcc758574 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -33,29 +33,41 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; *

The interface for Bluetooth Sockets is similar to that of TCP sockets: * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server * side, use a {@link BluetoothServerSocket} to create a listening server - * socket. It will return a new, connected {@link BluetoothSocket} on an - * accepted connection. On the client side, use the same - * {@link BluetoothSocket} object to both intiate the outgoing connection, - * and to manage the connected socket. + * socket. When a connection is accepted by the {@link BluetoothServerSocket}, + * it will return a new {@link BluetoothSocket} to manage the connection. + * On the client side, use a single {@link BluetoothSocket} to both intiate + * an outgoing connection and to manage the connection. * - *

The most common type of Bluetooth Socket is RFCOMM. RFCOMM is a - * connection orientated, streaming transport over Bluetooth. It is also known - * as the Serial Port Profile (SPP). + *

The most common type of Bluetooth socket is RFCOMM, which is the type + * supported by the Android APIs. RFCOMM is a connection-oriented, streaming + * transport over Bluetooth. It is also known as the Serial Port Profile (SPP). * - *

Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to create - * a new {@link BluetoothSocket} ready for an outgoing connection to a remote - * {@link BluetoothDevice}. + *

To create a {@link BluetoothSocket} for connecting to a known device, use + * {@link BluetoothDevice#createRfcommSocketToServiceRecord + * BluetoothDevice.createRfcommSocketToServiceRecord()}. + * Then call {@link #connect()} to attempt a connection to the remote device. + * This call will block until a connection is established or the connection + * fails. * - *

Use {@link BluetoothAdapter#listenUsingRfcommWithServiceRecord} to - * create a listening {@link BluetoothServerSocket} ready for incoming - * connections to the local {@link BluetoothAdapter}. + *

To create a {@link BluetoothSocket} as a server (or "host"), see the + * {@link BluetoothServerSocket} documentation. * - *

{@link BluetoothSocket} and {@link BluetoothServerSocket} are thread + *

Once the socket is connected, whether initiated as a client or accepted + * as a server, open the IO streams by calling {@link #getInputStream} and + * {@link #getOutputStream} in order to retrieve {@link java.io.InputStream} + * and {@link java.io.OutputStream} objects, respectively, which are + * automatically connected to the socket. + * + *

{@link BluetoothSocket} is thread * safe. In particular, {@link #close} will always immediately abort ongoing * operations and close the socket. * - *

All methods on a {@link BluetoothSocket} require - * {@link android.Manifest.permission#BLUETOOTH} + *

Note: + * Requires the {@link android.Manifest.permission#BLUETOOTH} permission. + * + * {@see BluetoothServerSocket} + * {@see java.io.InputStream} + * {@see java.io.OutputStream} */ public final class BluetoothSocket implements Closeable { private static final String TAG = "BluetoothSocket"; -- cgit v1.2.3 From a7848ce834a484d194d05afd8097ab3014f9b449 Mon Sep 17 00:00:00 2001 From: Scott Main Date: Thu, 19 Nov 2009 17:00:19 -0800 Subject: docs for ESR: add docs to bluetooth explainin that discovery should be cancelled before connecting to a device bug: 2160782,2198463 --- framework/java/android/bluetooth/BluetoothSocket.java | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index dbcc758574..ad033999e0 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -180,6 +180,15 @@ public final class BluetoothSocket implements Closeable { *

This method will block until a connection is made or the connection * fails. If this method returns without an exception then this socket * is now connected. + *

Creating new connections to + * remote Bluetooth devices should not be attempted while device discovery + * is in progress. Device discovery is a heavyweight procedure on the + * Bluetooth adapter and will significantly slow a device connection. + * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing + * discovery. Discovery is not managed by the Activity, + * but is run as a system service, so an application should always call + * {@link BluetoothAdapter#cancelDiscovery()} even if it + * did not directly request a discovery, just to be sure. *

{@link #close} can be used to abort this call from another thread. * @throws IOException on error, for example connection failure */ -- cgit v1.2.3 From 04c7138c7c1f36d54fbe33c40644e197248166b9 Mon Sep 17 00:00:00 2001 From: Jake Hamby Date: Tue, 21 Sep 2010 13:39:53 -0700 Subject: Typo fixes in comments and minor code cleanups. * Fix some typos in Javadoc and log messages. * Remove redundant initializer in BluetoothAdapter.readOutOfBandData() * Use canonical "UTF-8" charset name instead of "UTF8" in BluetoothDevice.convertPinToBytes() Change-Id: I58cd5dc48a7ad0053d204c5f590b4b3d438d8672 --- framework/java/android/bluetooth/BluetoothSocket.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index ad033999e0..719d730770 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -35,7 +35,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * side, use a {@link BluetoothServerSocket} to create a listening server * socket. When a connection is accepted by the {@link BluetoothServerSocket}, * it will return a new {@link BluetoothSocket} to manage the connection. - * On the client side, use a single {@link BluetoothSocket} to both intiate + * On the client side, use a single {@link BluetoothSocket} to both initiate * an outgoing connection and to manage the connection. * *

The most common type of Bluetooth socket is RFCOMM, which is the type @@ -113,7 +113,7 @@ public final class BluetoothSocket implements Closeable { * @param port remote port * @param uuid SDP uuid * @throws IOException On error, for example Bluetooth not available, or - * insufficient priveleges + * insufficient privileges */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid) throws IOException { @@ -158,7 +158,7 @@ public final class BluetoothSocket implements Closeable { * @param address remote device that this socket can connect to * @param port remote port * @throws IOException On error, for example Bluetooth not available, or - * insufficient priveleges + * insufficient privileges */ private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port) throws IOException { @@ -226,7 +226,7 @@ public final class BluetoothSocket implements Closeable { } // all native calls are guaranteed to immediately return after - // abortNative(), so this lock should immediatley acquire + // abortNative(), so this lock should immediately acquire mLock.writeLock().lock(); try { mClosed = true; -- cgit v1.2.3 From 638350f52c9dd10f72709bf19bd3010225478dae Mon Sep 17 00:00:00 2001 From: Matthew Xie Date: Tue, 3 May 2011 19:50:20 -0700 Subject: Add public api BluetoothSocket.isConnected. It's a convenent function to get the connection status of the bluetooth socket, ie, whether there is an active connection with remote device. bug 2149043 Change-Id: I4ca4e98c646f70746d838632f3035376b22d579b --- .../java/android/bluetooth/BluetoothSocket.java | 44 ++++++++++++++++------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 719d730770..9a13c3eb07 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -94,10 +94,16 @@ public final class BluetoothSocket implements Closeable { private int mPort; /* RFCOMM channel or L2CAP psm */ + private enum SocketState { + INIT, + CONNECTED, + CLOSED + } + /** prevents all native calls after destroyNative() */ - private boolean mClosed; + private SocketState mSocketState; - /** protects mClosed */ + /** protects mSocketState */ private final ReentrantReadWriteLock mLock; /** used by native code only */ @@ -145,7 +151,7 @@ public final class BluetoothSocket implements Closeable { } mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); - mClosed = false; + mSocketState = SocketState.INIT; mLock = new ReentrantReadWriteLock(); } @@ -195,13 +201,14 @@ public final class BluetoothSocket implements Closeable { public void connect() throws IOException { mLock.readLock().lock(); try { - if (mClosed) throw new IOException("socket closed"); + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); if (mSdp != null) { mPort = mSdp.doSdp(); // blocks } connectNative(); // blocks + mSocketState = SocketState.CONNECTED; } finally { mLock.readLock().unlock(); } @@ -216,7 +223,7 @@ public final class BluetoothSocket implements Closeable { // abort blocking operations on the socket mLock.readLock().lock(); try { - if (mClosed) return; + if (mSocketState == SocketState.CLOSED) return; if (mSdp != null) { mSdp.cancel(); } @@ -229,7 +236,7 @@ public final class BluetoothSocket implements Closeable { // abortNative(), so this lock should immediately acquire mLock.writeLock().lock(); try { - mClosed = true; + mSocketState = SocketState.CLOSED; destroyNative(); } finally { mLock.writeLock().unlock(); @@ -266,6 +273,16 @@ public final class BluetoothSocket implements Closeable { return mOutputStream; } + /** + * Get the connection status of this socket, ie, whether there is an active connection with + * remote device. + * @return true if connected + * false if not connected + */ + public boolean isConnected() { + return (mSocketState == SocketState.CONNECTED); + } + /** * Currently returns unix errno instead of throwing IOException, * so that BluetoothAdapter can check the error code for EADDRINUSE @@ -273,7 +290,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ int bindListen() { mLock.readLock().lock(); try { - if (mClosed) return EBADFD; + if (mSocketState == SocketState.CLOSED) return EBADFD; return bindListenNative(); } finally { mLock.readLock().unlock(); @@ -283,8 +300,11 @@ public final class BluetoothSocket implements Closeable { /*package*/ BluetoothSocket accept(int timeout) throws IOException { mLock.readLock().lock(); try { - if (mClosed) throw new IOException("socket closed"); - return acceptNative(timeout); + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + + BluetoothSocket acceptedSocket = acceptNative(timeout); + mSocketState = SocketState.CONNECTED; + return acceptedSocket; } finally { mLock.readLock().unlock(); } @@ -293,7 +313,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ int available() throws IOException { mLock.readLock().lock(); try { - if (mClosed) throw new IOException("socket closed"); + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); return availableNative(); } finally { mLock.readLock().unlock(); @@ -303,7 +323,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ int read(byte[] b, int offset, int length) throws IOException { mLock.readLock().lock(); try { - if (mClosed) throw new IOException("socket closed"); + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); return readNative(b, offset, length); } finally { mLock.readLock().unlock(); @@ -313,7 +333,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ int write(byte[] b, int offset, int length) throws IOException { mLock.readLock().lock(); try { - if (mClosed) throw new IOException("socket closed"); + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); return writeNative(b, offset, length); } finally { mLock.readLock().unlock(); -- cgit v1.2.3 From da4e2ab44781662822e2f8ee1f94f2085309d66d Mon Sep 17 00:00:00 2001 From: Joe Fernandez Date: Tue, 20 Dec 2011 10:38:34 -0800 Subject: docs: Add developer guide cross-references, Project ACRE, round 4 Change-Id: I1b43414aaec8ea217b39a0d780c80a25409d0991 --- framework/java/android/bluetooth/BluetoothSocket.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 9a13c3eb07..19d13ef345 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -65,6 +65,12 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; *

Note: * Requires the {@link android.Manifest.permission#BLUETOOTH} permission. * + *

+ *

Developer Guides

+ *

For more information about using Bluetooth, read the + * Bluetooth developer guide.

+ *
+ * * {@see BluetoothServerSocket} * {@see java.io.InputStream} * {@see java.io.OutputStream} -- cgit v1.2.3 From f73ea4f505cc15fc5c2c32c21beb7cc485a0ba47 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Thu, 3 May 2012 19:46:01 -0700 Subject: Avoid calling BluetoothSocket.destroyNative twice If the destroyNative JNI method is called twice, it will attempt to free the socketData twice, and the second free will cause an assertion failure. To avoid this, check whether mSocketState has already been set to CLOSED while holding the write lock. If it has, then destroyNative has already been called and should not be called again. Bug: 3096033 Change-Id: Ic7c0bbf21823d389b26919da8c533d8ac4d49064 --- framework/java/android/bluetooth/BluetoothSocket.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 19d13ef345..20e8515608 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -242,8 +242,10 @@ public final class BluetoothSocket implements Closeable { // abortNative(), so this lock should immediately acquire mLock.writeLock().lock(); try { - mSocketState = SocketState.CLOSED; - destroyNative(); + if (mSocketState != SocketState.CLOSED) { + mSocketState = SocketState.CLOSED; + destroyNative(); + } } finally { mLock.writeLock().unlock(); } -- cgit v1.2.3 From 884452306d321a159f432fbec2573d2f37e513c5 Mon Sep 17 00:00:00 2001 From: Jaikumar Ganesh Date: Wed, 25 Jan 2012 16:16:48 -0800 Subject: Changes for new Bluetooth APIs. Changes to Bluetooth Adapter, Device and IBluetooth interfaces for new Bluetooth APIs. Delete AudioGateway. Change-Id: Ib51b31187eafde261441b9311b5e7e13c8bff82f --- framework/java/android/bluetooth/BluetoothSocket.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 20e8515608..2662f39169 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -150,11 +150,14 @@ public final class BluetoothSocket implements Closeable { } else { mAddress = device.getAddress(); } + + //TODO(BT) + /* if (fd == -1) { initSocketNative(); } else { initSocketFromFdNative(fd); - } + }*/ mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); mSocketState = SocketState.INIT; @@ -227,6 +230,8 @@ public final class BluetoothSocket implements Closeable { */ public void close() throws IOException { // abort blocking operations on the socket + //TODO(BT) + /* mLock.readLock().lock(); try { if (mSocketState == SocketState.CLOSED) return; @@ -248,7 +253,7 @@ public final class BluetoothSocket implements Closeable { } } finally { mLock.writeLock().unlock(); - } + }*/ } /** @@ -296,13 +301,16 @@ public final class BluetoothSocket implements Closeable { * so that BluetoothAdapter can check the error code for EADDRINUSE */ /*package*/ int bindListen() { + return -1; + //TODO(BT) + /* mLock.readLock().lock(); try { if (mSocketState == SocketState.CLOSED) return EBADFD; return bindListenNative(); } finally { mLock.readLock().unlock(); - } + }*/ } /*package*/ BluetoothSocket accept(int timeout) throws IOException { @@ -388,9 +396,11 @@ public final class BluetoothSocket implements Closeable { channel = -1; boolean inProgress = false; + //TODO(BT) + /* try { inProgress = service.fetchRemoteUuids(device.getAddress(), uuid, this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) {Log.e(TAG, "", e);}*/ if (!inProgress) throw new IOException("Unable to start Service Discovery"); -- cgit v1.2.3 From fab62db7cf9962e90bfe30b85df57b6c621b7310 Mon Sep 17 00:00:00 2001 From: zzy Date: Tue, 3 Apr 2012 19:48:32 -0700 Subject: Added new rfcomm multi accept code --- .../java/android/bluetooth/BluetoothSocket.java | 501 ++++++++++++--------- 1 file changed, 281 insertions(+), 220 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 2662f39169..9b0e1cb2c1 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -1,32 +1,27 @@ /* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright (C) 2012 Google Inc. */ package android.bluetooth; -import android.bluetooth.IBluetoothCallback; +import android.os.IBinder; import android.os.ParcelUuid; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; import java.io.Closeable; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.concurrent.locks.ReentrantReadWriteLock; - +import java.util.List; +import android.net.LocalSocket; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; /** * A connected or connecting Bluetooth socket. * @@ -89,31 +84,41 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int EBADFD = 77; /*package*/ static final int EADDRINUSE = 98; + /*package*/ static final int SEC_FLAG_ENCRYPT = 1; + /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; + private final int mType; /* one of TYPE_RFCOMM etc */ - private final BluetoothDevice mDevice; /* remote device */ - private final String mAddress; /* remote address */ + private BluetoothDevice mDevice; /* remote device */ + private String mAddress; /* remote address */ private final boolean mAuth; private final boolean mEncrypt; private final BluetoothInputStream mInputStream; private final BluetoothOutputStream mOutputStream; - private final SdpHelper mSdp; - + private final ParcelUuid mUuid; + private ParcelFileDescriptor mPfd; + private LocalSocket mSocket; + private InputStream mSocketIS; + private OutputStream mSocketOS; private int mPort; /* RFCOMM channel or L2CAP psm */ + private int mFd; + private String mServiceName; + private static IBluetooth sBluetoothProxy; + private static int PROXY_CONNECTION_TIMEOUT = 5000; + + private static int SOCK_SIGNAL_SIZE = 16; private enum SocketState { INIT, CONNECTED, - CLOSED + LISTENING, + CLOSED, } /** prevents all native calls after destroyNative() */ - private SocketState mSocketState; + private volatile SocketState mSocketState; /** protects mSocketState */ - private final ReentrantReadWriteLock mLock; - - /** used by native code only */ - private int mSocketData; + //private final ReentrantReadWriteLock mLock; /** * Construct a BluetoothSocket. @@ -134,36 +139,63 @@ public final class BluetoothSocket implements Closeable { throw new IOException("Invalid RFCOMM channel: " + port); } } - if (uuid == null) { - mPort = port; - mSdp = null; - } else { - mSdp = new SdpHelper(device, uuid); - mPort = -1; - } + mUuid = uuid; mType = type; mAuth = auth; mEncrypt = encrypt; mDevice = device; + mPort = port; + mFd = fd; + + mSocketState = SocketState.INIT; + if (device == null) { - mAddress = null; + // Server socket + mAddress = BluetoothAdapter.getDefaultAdapter().getAddress(); } else { + // Remote socket mAddress = device.getAddress(); } + mInputStream = new BluetoothInputStream(this); + mOutputStream = new BluetoothOutputStream(this); - //TODO(BT) - /* - if (fd == -1) { - initSocketNative(); - } else { - initSocketFromFdNative(fd); - }*/ + if (sBluetoothProxy == null) { + synchronized (BluetoothSocket.class) { + if (sBluetoothProxy == null) { + IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE); + if (b == null) + throw new RuntimeException("Bluetooth service not available"); + sBluetoothProxy = IBluetooth.Stub.asInterface(b); + } + } + } + } + private BluetoothSocket(BluetoothSocket s) { + mUuid = s.mUuid; + mType = s.mType; + mAuth = s.mAuth; + mEncrypt = s.mEncrypt; + mPort = s.mPort; mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); - mSocketState = SocketState.INIT; - mLock = new ReentrantReadWriteLock(); + mServiceName = s.mServiceName; + } + private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException { + BluetoothSocket as = new BluetoothSocket(this); + as.mSocketState = SocketState.CONNECTED; + FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors(); + Log.d(TAG, "socket fd passed by stack fds: " + fds); + if(fds == null || fds.length != 1) { + Log.e(TAG, "socket fd passed from stack failed, fds: " + fds); + throw new IOException("bt socket acept failed"); + } + as.mSocket = new LocalSocket(fds[0]); + as.mSocketIS = as.mSocket.getInputStream(); + as.mSocketOS = as.mSocket.getOutputStream(); + as.mAddress = RemoteAddr; + as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(RemoteAddr); + return as; } - /** * Construct a BluetoothSocket from address. Used by native code. * @param type type of socket @@ -189,71 +221,13 @@ public final class BluetoothSocket implements Closeable { super.finalize(); } } - - /** - * Attempt to connect to a remote device. - *

This method will block until a connection is made or the connection - * fails. If this method returns without an exception then this socket - * is now connected. - *

Creating new connections to - * remote Bluetooth devices should not be attempted while device discovery - * is in progress. Device discovery is a heavyweight procedure on the - * Bluetooth adapter and will significantly slow a device connection. - * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing - * discovery. Discovery is not managed by the Activity, - * but is run as a system service, so an application should always call - * {@link BluetoothAdapter#cancelDiscovery()} even if it - * did not directly request a discovery, just to be sure. - *

{@link #close} can be used to abort this call from another thread. - * @throws IOException on error, for example connection failure - */ - public void connect() throws IOException { - mLock.readLock().lock(); - try { - if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); - - if (mSdp != null) { - mPort = mSdp.doSdp(); // blocks - } - - connectNative(); // blocks - mSocketState = SocketState.CONNECTED; - } finally { - mLock.readLock().unlock(); - } - } - - /** - * Immediately close this socket, and release all associated resources. - *

Causes blocked calls on this socket in other threads to immediately - * throw an IOException. - */ - public void close() throws IOException { - // abort blocking operations on the socket - //TODO(BT) - /* - mLock.readLock().lock(); - try { - if (mSocketState == SocketState.CLOSED) return; - if (mSdp != null) { - mSdp.cancel(); - } - abortNative(); - } finally { - mLock.readLock().unlock(); - } - - // all native calls are guaranteed to immediately return after - // abortNative(), so this lock should immediately acquire - mLock.writeLock().lock(); - try { - if (mSocketState != SocketState.CLOSED) { - mSocketState = SocketState.CLOSED; - destroyNative(); - } - } finally { - mLock.writeLock().unlock(); - }*/ + private int getSecurityFlags() { + int flags = 0; + if(mAuth) + flags |= SEC_FLAG_AUTH; + if(mEncrypt) + flags |= SEC_FLAG_ENCRYPT; + return flags; } /** @@ -293,7 +267,63 @@ public final class BluetoothSocket implements Closeable { * false if not connected */ public boolean isConnected() { - return (mSocketState == SocketState.CONNECTED); + return mSocketState == SocketState.CONNECTED; + } + + /*package*/ void setServiceName(String name) { + mServiceName = name; + } + + /** + * Attempt to connect to a remote device. + *

This method will block until a connection is made or the connection + * fails. If this method returns without an exception then this socket + * is now connected. + *

Creating new connections to + * remote Bluetooth devices should not be attempted while device discovery + * is in progress. Device discovery is a heavyweight procedure on the + * Bluetooth adapter and will significantly slow a device connection. + * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing + * discovery. Discovery is not managed by the Activity, + * but is run as a system service, so an application should always call + * {@link BluetoothAdapter#cancelDiscovery()} even if it + * did not directly request a discovery, just to be sure. + *

{@link #close} can be used to abort this call from another thread. + * @throws IOException on error, for example connection failure + */ + public void connect() throws IOException { + if (mDevice == null) throw new IOException("Connect is called on null device"); + + try { + // TODO(BT) derive flag from auth and encrypt + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + + mPfd = sBluetoothProxy.connectSocket(mDevice, mType, + mUuid, mPort, getSecurityFlags()); + synchronized(this) + { + Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd); + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + if (mPfd == null) throw new IOException("bt socket connect failed"); + FileDescriptor fd = mPfd.getFileDescriptor(); + mSocket = new LocalSocket(fd); + mSocketIS = mSocket.getInputStream(); + mSocketOS = mSocket.getOutputStream(); + } + int channel = readInt(mSocketIS); + if (channel <= 0) + throw new IOException("bt socket connect failed"); + mPort = channel; + waitSocketSignal(mSocketIS); + synchronized(this) + { + if (mSocketState == SocketState.CLOSED) + throw new IOException("bt socket closed"); + mSocketState = SocketState.CONNECTED; + } + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } } /** @@ -301,134 +331,165 @@ public final class BluetoothSocket implements Closeable { * so that BluetoothAdapter can check the error code for EADDRINUSE */ /*package*/ int bindListen() { - return -1; - //TODO(BT) - /* - mLock.readLock().lock(); + int ret; + if (mSocketState == SocketState.CLOSED) return EBADFD; try { - if (mSocketState == SocketState.CLOSED) return EBADFD; - return bindListenNative(); - } finally { - mLock.readLock().unlock(); - }*/ - } + mPfd = sBluetoothProxy.createSocketChannel(mType, mServiceName, + mUuid, mPort, getSecurityFlags()); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + // TODO(BT) right error code? + return -1; + } - /*package*/ BluetoothSocket accept(int timeout) throws IOException { - mLock.readLock().lock(); + // read out port number try { - if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + synchronized(this) { + Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd); + if(mSocketState != SocketState.INIT) return EBADFD; + if(mPfd == null) return -1; + FileDescriptor fd = mPfd.getFileDescriptor(); + Log.d(TAG, "bindListen(), new LocalSocket "); + mSocket = new LocalSocket(fd); + Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() "); + mSocketIS = mSocket.getInputStream(); + mSocketOS = mSocket.getOutputStream(); + } + Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS); + int channel = readInt(mSocketIS); + synchronized(this) { + if(mSocketState == SocketState.INIT) + mSocketState = SocketState.LISTENING; + } + Log.d(TAG, "channel: " + channel); + if (mPort == -1) { + mPort = channel; + } // else ASSERT(mPort == channel) + ret = 0; + } catch (IOException e) { + Log.e(TAG, "bindListen, fail to get port number, exception: " + e); + return -1; + } + return ret; + } - BluetoothSocket acceptedSocket = acceptNative(timeout); - mSocketState = SocketState.CONNECTED; - return acceptedSocket; - } finally { - mLock.readLock().unlock(); + /*package*/ BluetoothSocket accept(int timeout) throws IOException { + BluetoothSocket acceptedSocket; + if (mSocketState != SocketState.LISTENING) throw new IOException("bt socket is not in listen state"); + // TODO(BT) wait on an incoming connection + String RemoteAddr = waitSocketSignal(mSocketIS); + synchronized(this) + { + if (mSocketState != SocketState.LISTENING) + throw new IOException("bt socket is not in listen state"); + acceptedSocket = acceptSocket(RemoteAddr); + //quick drop the reference of the file handle } + // TODO(BT) rfcomm socket only supports one connection, return this? + // return this; + return acceptedSocket; } /*package*/ int available() throws IOException { - mLock.readLock().lock(); - try { - if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); - return availableNative(); - } finally { - mLock.readLock().unlock(); - } + Log.d(TAG, "available: " + mSocketIS); + return mSocketIS.available(); } /*package*/ int read(byte[] b, int offset, int length) throws IOException { - mLock.readLock().lock(); - try { - if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); - return readNative(b, offset, length); - } finally { - mLock.readLock().unlock(); - } + + Log.d(TAG, "read in: " + mSocketIS + " len: " + length); + int ret = mSocketIS.read(b, offset, length); + if(ret < 0) + throw new IOException("bt socket closed, read return: " + ret); + Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); + return ret; } /*package*/ int write(byte[] b, int offset, int length) throws IOException { - mLock.readLock().lock(); - try { - if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); - return writeNative(b, offset, length); - } finally { - mLock.readLock().unlock(); + + Log.d(TAG, "write: " + mSocketOS + " length: " + length); + mSocketOS.write(b, offset, length); + // There is no good way to confirm since the entire process is asynchronous anyway + Log.d(TAG, "write out: " + mSocketOS + " length: " + length); + return length; + } + + @Override + public void close() throws IOException { + Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState); + if(mSocketState == SocketState.CLOSED) + return; + else + { + synchronized(this) + { + if(mSocketState == SocketState.CLOSED) + return; + mSocketState = SocketState.CLOSED; + Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS + + ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket); + if(mSocket != null) { + Log.d(TAG, "Closing mSocket: " + mSocket); + mSocket.shutdownInput(); + mSocket.shutdownOutput(); + mSocket.close(); + mSocket = null; + } + if(mPfd != null) + mPfd.detachFd(); + } } + // TODO(BT) unbind proxy, } - private native void initSocketNative() throws IOException; - private native void initSocketFromFdNative(int fd) throws IOException; - private native void connectNative() throws IOException; - private native int bindListenNative(); - 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; - /** - * Throws an IOException for given posix errno. Done natively so we can - * use strerr to convert to string error. - */ - /*package*/ native void throwErrnoNative(int errno) throws IOException; + /*package */ void removeChannel() { + } - /** - * Helper to perform blocking SDP lookup. - */ - private static class SdpHelper extends IBluetoothCallback.Stub { - private final IBluetooth service; - private final ParcelUuid uuid; - private final BluetoothDevice device; - private int channel; - private boolean canceled; - public SdpHelper(BluetoothDevice device, ParcelUuid uuid) { - service = BluetoothDevice.getService(); - this.device = device; - this.uuid = uuid; - canceled = false; - } - /** - * Returns the RFCOMM channel for the UUID, or throws IOException - * on failure. - */ - public synchronized int doSdp() throws IOException { - if (canceled) throw new IOException("Service discovery canceled"); - channel = -1; - - boolean inProgress = false; - //TODO(BT) - /* - try { - inProgress = service.fetchRemoteUuids(device.getAddress(), uuid, this); - } catch (RemoteException e) {Log.e(TAG, "", e);}*/ - - if (!inProgress) throw new IOException("Unable to start Service Discovery"); - - try { - /* 12 second timeout as a precaution - onRfcommChannelFound - * should always occur before the timeout */ - wait(12000); // block - - } catch (InterruptedException e) {} - - if (canceled) throw new IOException("Service discovery canceled"); - if (channel < 1) throw new IOException("Service discovery failed"); - - return channel; - } - /** Object cannot be re-used after calling cancel() */ - public synchronized void cancel() { - if (!canceled) { - canceled = true; - channel = -1; - notifyAll(); // unblock - } - } - public synchronized void onRfcommChannelFound(int channel) { - if (!canceled) { - this.channel = channel; - notifyAll(); // unblock - } + /*package */ int getPort() { + return mPort; + } + private String convertAddr(final byte[] addr) { + return String.format("%02X:%02X:%02X:%02X:%02X:%02X", + addr[0] , addr[1], addr[2], addr[3] , addr[4], addr[5]); + } + private String waitSocketSignal(InputStream is) throws IOException { + byte [] sig = new byte[SOCK_SIGNAL_SIZE]; + int ret = readAll(is, sig); + Log.d(TAG, "waitSocketSignal read 16 bytes signal ret: " + ret); + ByteBuffer bb = ByteBuffer.wrap(sig); + bb.order(ByteOrder.nativeOrder()); + int size = bb.getShort(); + byte [] addr = new byte[6]; + bb.get(addr); + int channel = bb.getInt(); + int status = bb.getInt(); + String RemoteAddr = convertAddr(addr); + Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: " + + RemoteAddr + ", channel: " + channel + ", status: " + status); + if(status != 0) + throw new IOException("Connection failure, status: " + status); + return RemoteAddr; + } + private int readAll(InputStream is, byte[] b) throws IOException { + int left = b.length; + while(left > 0) { + int ret = is.read(b, b.length - left, left); + if(ret < 0) + throw new IOException("read failed, socket might closed, read ret: " + ret); + left -= ret; + if(left != 0) + Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) + + ", expect size: " + b.length); } + return b.length; + } + + private int readInt(InputStream is) throws IOException { + byte[] ibytes = new byte[4]; + int ret = readAll(is, ibytes); + Log.d(TAG, "inputStream.read ret: " + ret); + ByteBuffer bb = ByteBuffer.wrap(ibytes); + bb.order(ByteOrder.nativeOrder()); + return bb.getInt(); } } -- cgit v1.2.3 From 3c7196448a62414bf1bfcc94947bfcfa2d60278a Mon Sep 17 00:00:00 2001 From: fredc Date: Thu, 12 Apr 2012 00:02:00 -0700 Subject: Non persistent adapter service Change-Id: Ib13d5c77416e58161df0e04d7a15ec0dddbde8b5 Conflicts: core/java/android/bluetooth/BluetoothInputDevice.java Conflicts: core/java/com/android/internal/app/ShutdownThread.java services/java/com/android/server/SystemServer.java Conflicts: services/java/com/android/server/SystemServer.java services/java/com/android/server/pm/ShutdownThread.java --- .../java/android/bluetooth/BluetoothSocket.java | 24 ++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 9b0e1cb2c1..d37f2d5384 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -102,7 +102,6 @@ public final class BluetoothSocket implements Closeable { private int mPort; /* RFCOMM channel or L2CAP psm */ private int mFd; private String mServiceName; - private static IBluetooth sBluetoothProxy; private static int PROXY_CONNECTION_TIMEOUT = 5000; private static int SOCK_SIGNAL_SIZE = 16; @@ -158,17 +157,6 @@ public final class BluetoothSocket implements Closeable { } mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); - - if (sBluetoothProxy == null) { - synchronized (BluetoothSocket.class) { - if (sBluetoothProxy == null) { - IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE); - if (b == null) - throw new RuntimeException("Bluetooth service not available"); - sBluetoothProxy = IBluetooth.Stub.asInterface(b); - } - } - } } private BluetoothSocket(BluetoothSocket s) { mUuid = s.mUuid; @@ -297,8 +285,9 @@ public final class BluetoothSocket implements Closeable { try { // TODO(BT) derive flag from auth and encrypt if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); - - mPfd = sBluetoothProxy.connectSocket(mDevice, mType, + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(); + if (bluetoothProxy == null) throw new IOException("Bluetooth is off"); + mPfd = bluetoothProxy.connectSocket(mDevice, mType, mUuid, mPort, getSecurityFlags()); synchronized(this) { @@ -333,8 +322,13 @@ public final class BluetoothSocket implements Closeable { /*package*/ int bindListen() { int ret; if (mSocketState == SocketState.CLOSED) return EBADFD; + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(); + if (bluetoothProxy == null) { + Log.e(TAG, "bindListen fail, reason: bluetooth is off"); + return -1; + } try { - mPfd = sBluetoothProxy.createSocketChannel(mType, mServiceName, + mPfd = bluetoothProxy.createSocketChannel(mType, mServiceName, mUuid, mPort, getSecurityFlags()); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); -- cgit v1.2.3 From f1f5dde555c09019c0cedb05e844adf288677bc5 Mon Sep 17 00:00:00 2001 From: fredc Date: Tue, 24 Apr 2012 03:59:57 -0700 Subject: Fixed issue with Settings app crashing after during on/off and unpair. Fixed issue with BluetoothAdapter.getRemoteDevice() returning null. Change-Id: Ie86813532530a6b57bde1c430c7b4875ecc7354c --- framework/java/android/bluetooth/BluetoothSocket.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d37f2d5384..221b1a3c85 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -285,7 +285,7 @@ public final class BluetoothSocket implements Closeable { try { // TODO(BT) derive flag from auth and encrypt if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); - IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); if (bluetoothProxy == null) throw new IOException("Bluetooth is off"); mPfd = bluetoothProxy.connectSocket(mDevice, mType, mUuid, mPort, getSecurityFlags()); @@ -322,7 +322,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ int bindListen() { int ret; if (mSocketState == SocketState.CLOSED) return EBADFD; - IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); if (bluetoothProxy == null) { Log.e(TAG, "bindListen fail, reason: bluetooth is off"); return -1; -- cgit v1.2.3 From e8d151968574b4ec435e5b133d07fe67888ca22f Mon Sep 17 00:00:00 2001 From: fredc Date: Wed, 25 Apr 2012 17:46:13 -0700 Subject: Fixed socket not closing on BT off. Used RemoteCallbackList to monitor binder deaths in BluetoothManagerService. Change-Id: I524964bd2836d8c5a4bae095b93ac9481337941d --- framework/java/android/bluetooth/BluetoothSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 221b1a3c85..1bc640ff59 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -468,7 +468,7 @@ public final class BluetoothSocket implements Closeable { int left = b.length; while(left > 0) { int ret = is.read(b, b.length - left, left); - if(ret < 0) + if(ret <= 0) throw new IOException("read failed, socket might closed, read ret: " + ret); left -= ret; if(left != 0) -- cgit v1.2.3 From f8035a79ebb19a8c96197ea7a4daf82c5ce4464f Mon Sep 17 00:00:00 2001 From: Matthew Xie Date: Tue, 9 Oct 2012 22:10:37 -0700 Subject: Reduce android.bluetooth package debug messages bug 7174712 Change-Id: I8d3fdc8edbe42068b5a550660d7b24854c3c4af4 --- .../java/android/bluetooth/BluetoothSocket.java | 37 ++++++++++++---------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 1bc640ff59..aba87106d9 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -72,6 +72,8 @@ import java.nio.ByteBuffer; */ public final class BluetoothSocket implements Closeable { private static final String TAG = "BluetoothSocket"; + private static final boolean DBG = true; + private static final boolean VDBG = false; /** @hide */ public static final int MAX_RFCOMM_CHANNEL = 30; @@ -172,7 +174,7 @@ public final class BluetoothSocket implements Closeable { BluetoothSocket as = new BluetoothSocket(this); as.mSocketState = SocketState.CONNECTED; FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors(); - Log.d(TAG, "socket fd passed by stack fds: " + fds); + if (VDBG) Log.d(TAG, "socket fd passed by stack fds: " + fds); if(fds == null || fds.length != 1) { Log.e(TAG, "socket fd passed from stack failed, fds: " + fds); throw new IOException("bt socket acept failed"); @@ -291,7 +293,7 @@ public final class BluetoothSocket implements Closeable { mUuid, mPort, getSecurityFlags()); synchronized(this) { - Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd); + if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd); if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); if (mPfd == null) throw new IOException("bt socket connect failed"); FileDescriptor fd = mPfd.getFileDescriptor(); @@ -339,23 +341,24 @@ public final class BluetoothSocket implements Closeable { // read out port number try { synchronized(this) { - Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd); + if (VDBG) Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + + mPfd); if(mSocketState != SocketState.INIT) return EBADFD; if(mPfd == null) return -1; FileDescriptor fd = mPfd.getFileDescriptor(); - Log.d(TAG, "bindListen(), new LocalSocket "); + if (VDBG) Log.d(TAG, "bindListen(), new LocalSocket "); mSocket = new LocalSocket(fd); - Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() "); + if (VDBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() "); mSocketIS = mSocket.getInputStream(); mSocketOS = mSocket.getOutputStream(); } - Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS); + if (VDBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS); int channel = readInt(mSocketIS); synchronized(this) { if(mSocketState == SocketState.INIT) mSocketState = SocketState.LISTENING; } - Log.d(TAG, "channel: " + channel); + if (VDBG) Log.d(TAG, "channel: " + channel); if (mPort == -1) { mPort = channel; } // else ASSERT(mPort == channel) @@ -385,26 +388,26 @@ public final class BluetoothSocket implements Closeable { } /*package*/ int available() throws IOException { - Log.d(TAG, "available: " + mSocketIS); + if (VDBG) Log.d(TAG, "available: " + mSocketIS); return mSocketIS.available(); } /*package*/ int read(byte[] b, int offset, int length) throws IOException { - Log.d(TAG, "read in: " + mSocketIS + " len: " + length); + if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); int ret = mSocketIS.read(b, offset, length); if(ret < 0) throw new IOException("bt socket closed, read return: " + ret); - Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); + if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); return ret; } /*package*/ int write(byte[] b, int offset, int length) throws IOException { - Log.d(TAG, "write: " + mSocketOS + " length: " + length); + if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); mSocketOS.write(b, offset, length); // There is no good way to confirm since the entire process is asynchronous anyway - Log.d(TAG, "write out: " + mSocketOS + " length: " + length); + if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); return length; } @@ -420,10 +423,10 @@ public final class BluetoothSocket implements Closeable { if(mSocketState == SocketState.CLOSED) return; mSocketState = SocketState.CLOSED; - Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS + + if (VDBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket); if(mSocket != null) { - Log.d(TAG, "Closing mSocket: " + mSocket); + if (VDBG) Log.d(TAG, "Closing mSocket: " + mSocket); mSocket.shutdownInput(); mSocket.shutdownOutput(); mSocket.close(); @@ -449,7 +452,7 @@ public final class BluetoothSocket implements Closeable { private String waitSocketSignal(InputStream is) throws IOException { byte [] sig = new byte[SOCK_SIGNAL_SIZE]; int ret = readAll(is, sig); - Log.d(TAG, "waitSocketSignal read 16 bytes signal ret: " + ret); + if (VDBG) Log.d(TAG, "waitSocketSignal read 16 bytes signal ret: " + ret); ByteBuffer bb = ByteBuffer.wrap(sig); bb.order(ByteOrder.nativeOrder()); int size = bb.getShort(); @@ -458,7 +461,7 @@ public final class BluetoothSocket implements Closeable { int channel = bb.getInt(); int status = bb.getInt(); String RemoteAddr = convertAddr(addr); - Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: " + if (VDBG) Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: " + RemoteAddr + ", channel: " + channel + ", status: " + status); if(status != 0) throw new IOException("Connection failure, status: " + status); @@ -481,7 +484,7 @@ public final class BluetoothSocket implements Closeable { private int readInt(InputStream is) throws IOException { byte[] ibytes = new byte[4]; int ret = readAll(is, ibytes); - Log.d(TAG, "inputStream.read ret: " + ret); + if (VDBG) Log.d(TAG, "inputStream.read ret: " + ret); ByteBuffer bb = ByteBuffer.wrap(ibytes); bb.order(ByteOrder.nativeOrder()); return bb.getInt(); -- cgit v1.2.3 From 3049570708578ac0b5fd0ed2fd1793395028c7a0 Mon Sep 17 00:00:00 2001 From: zzy Date: Thu, 11 Oct 2012 14:52:43 -0700 Subject: Add serial port profile support and allow to connect to rfcomm channel without sdp discovery bug 7272974 Change-Id: Idc10edc056b48da2fd96bea84eba3fb73b97bab1 --- framework/java/android/bluetooth/BluetoothSocket.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index aba87106d9..8cbf5b1a5c 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; +import java.util.UUID; import android.net.LocalSocket; import java.nio.ByteOrder; import java.nio.ByteBuffer; @@ -140,7 +141,9 @@ public final class BluetoothSocket implements Closeable { throw new IOException("Invalid RFCOMM channel: " + port); } } - mUuid = uuid; + if(uuid != null) + mUuid = uuid; + else mUuid = new ParcelUuid(new UUID(0, 0)); mType = type; mAuth = auth; mEncrypt = encrypt; -- cgit v1.2.3 From a9cc57d090b3610c416d5b879b9fd05b2fea4a29 Mon Sep 17 00:00:00 2001 From: Zhihai Xu Date: Tue, 23 Oct 2012 17:31:56 -0700 Subject: License of files Bluetooth package is not updated to ASL2 bug 7385618 Change-Id: I6232f537f4fda979d3aabe3a059c11d3299de9b8 --- framework/java/android/bluetooth/BluetoothSocket.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 8cbf5b1a5c..26bde197ac 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -1,5 +1,17 @@ /* - * Copyright (C) 2012 Google Inc. + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package android.bluetooth; -- cgit v1.2.3 From 2e650b349052bcfd93fde6eb1e88aed8f77066a2 Mon Sep 17 00:00:00 2001 From: zzy Date: Thu, 22 Nov 2012 11:52:44 -0800 Subject: timeout support for accept() and added check for signal size bug 7592240 Change-Id: Ide1868da669c190cdfed90f7af3f739ec9da690b --- framework/java/android/bluetooth/BluetoothSocket.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 26bde197ac..d7a214d977 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -300,7 +300,6 @@ public final class BluetoothSocket implements Closeable { if (mDevice == null) throw new IOException("Connect is called on null device"); try { - // TODO(BT) derive flag from auth and encrypt if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); if (bluetoothProxy == null) throw new IOException("Bluetooth is off"); @@ -349,7 +348,6 @@ public final class BluetoothSocket implements Closeable { mUuid, mPort, getSecurityFlags()); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); - // TODO(BT) right error code? return -1; } @@ -388,8 +386,13 @@ public final class BluetoothSocket implements Closeable { /*package*/ BluetoothSocket accept(int timeout) throws IOException { BluetoothSocket acceptedSocket; if (mSocketState != SocketState.LISTENING) throw new IOException("bt socket is not in listen state"); - // TODO(BT) wait on an incoming connection + if(timeout > 0) { + Log.d(TAG, "accept() set timeout (ms):" + timeout); + mSocket.setSoTimeout(timeout); + } String RemoteAddr = waitSocketSignal(mSocketIS); + if(timeout > 0) + mSocket.setSoTimeout(0); synchronized(this) { if (mSocketState != SocketState.LISTENING) @@ -397,8 +400,6 @@ public final class BluetoothSocket implements Closeable { acceptedSocket = acceptSocket(RemoteAddr); //quick drop the reference of the file handle } - // TODO(BT) rfcomm socket only supports one connection, return this? - // return this; return acceptedSocket; } @@ -451,7 +452,6 @@ public final class BluetoothSocket implements Closeable { mPfd.detachFd(); } } - // TODO(BT) unbind proxy, } /*package */ void removeChannel() { @@ -471,6 +471,8 @@ public final class BluetoothSocket implements Closeable { ByteBuffer bb = ByteBuffer.wrap(sig); bb.order(ByteOrder.nativeOrder()); int size = bb.getShort(); + if(size != SOCK_SIGNAL_SIZE) + throw new IOException("Connection failure, wrong signal size: " + size); byte [] addr = new byte[6]; bb.get(addr); int channel = bb.getInt(); @@ -487,7 +489,7 @@ public final class BluetoothSocket implements Closeable { while(left > 0) { int ret = is.read(b, b.length - left, left); if(ret <= 0) - throw new IOException("read failed, socket might closed, read ret: " + ret); + throw new IOException("read failed, socket might closed or timeout, read ret: " + ret); left -= ret; if(left != 0) Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) + -- cgit v1.2.3 From a466c6c72a7dee9c1abf0f95cb3e3412072ffa94 Mon Sep 17 00:00:00 2001 From: Matthew Xie Date: Thu, 29 Nov 2012 20:26:19 -0800 Subject: Clean up debug messages bug 7626174 Change-Id: I65cdcaf2c48a78468b6cef0b8591289435068b24 --- framework/java/android/bluetooth/BluetoothSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d7a214d977..8029a1a25c 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -429,7 +429,7 @@ public final class BluetoothSocket implements Closeable { @Override public void close() throws IOException { - Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState); + if (VDBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState); if(mSocketState == SocketState.CLOSED) return; else -- cgit v1.2.3 From f6fcd9b26b8a1df94a02a0ff27f4f0fa3fcf7339 Mon Sep 17 00:00:00 2001 From: zzy Date: Tue, 16 Apr 2013 17:17:37 -0700 Subject: Added flush() for bluetooth output stream Bug 8498784 Zebra QL420 Plus Bluetooth printer fails on Android 4.2.2 --- framework/java/android/bluetooth/BluetoothSocket.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 8029a1a25c..a19341c07d 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -192,6 +192,7 @@ public final class BluetoothSocket implements Closeable { if (VDBG) Log.d(TAG, "socket fd passed by stack fds: " + fds); if(fds == null || fds.length != 1) { Log.e(TAG, "socket fd passed from stack failed, fds: " + fds); + as.close(); throw new IOException("bt socket acept failed"); } as.mSocket = new LocalSocket(fds[0]); @@ -407,6 +408,17 @@ public final class BluetoothSocket implements Closeable { if (VDBG) Log.d(TAG, "available: " + mSocketIS); return mSocketIS.available(); } + /** + * Wait until the data in sending queue is emptied. A polling version + * for flush implementation. Used to ensure the writing data afterwards will + * be packed in new RFCOMM frame. + * @throws IOException + * if an i/o error occurs. + */ + /*package*/ void flush() throws IOException { + if (VDBG) Log.d(TAG, "flush: " + mSocketOS); + mSocketOS.flush(); + } /*package*/ int read(byte[] b, int offset, int length) throws IOException { -- cgit v1.2.3 From c27359e696d9dd4aa89d77d3eb85c79348a206b5 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 11 Jun 2013 14:13:09 -0700 Subject: Explicit locale when formatting machine strings. Bug: 9390451 Change-Id: I3581c53407554a1dffd541fb42b06d68f20a7be0 --- framework/java/android/bluetooth/BluetoothSocket.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index a19341c07d..d10eaea2fb 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; +import java.util.Locale; import java.util.UUID; import android.net.LocalSocket; import java.nio.ByteOrder; @@ -473,7 +474,7 @@ public final class BluetoothSocket implements Closeable { return mPort; } private String convertAddr(final byte[] addr) { - return String.format("%02X:%02X:%02X:%02X:%02X:%02X", + return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0] , addr[1], addr[2], addr[3] , addr[4], addr[5]); } private String waitSocketSignal(InputStream is) throws IOException { -- cgit v1.2.3 From 626db853b28d64e493dd7b75073d2af838d0bc6a Mon Sep 17 00:00:00 2001 From: Zhihai Xu Date: Wed, 24 Jul 2013 15:09:45 -0700 Subject: Bluetooth stopped working in master - "bad file descriptor" ignore IllegalArgumentException in BluetoothSocket.close(). bug: 9960585 Change-Id: I301aa388b738dcb92b643fdd96b5c9cb6f8b3efe --- framework/java/android/bluetooth/BluetoothSocket.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d10eaea2fb..5c534a1e8c 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -461,8 +461,13 @@ public final class BluetoothSocket implements Closeable { mSocket.close(); mSocket = null; } - if(mPfd != null) - mPfd.detachFd(); + if(mPfd != null) { + try { + mPfd.detachFd(); + } catch (IllegalArgumentException e) { + Log.w(TAG, "ignore IllegalArgumentException"); + } + } } } } -- cgit v1.2.3 From b01210f0dec7a9b2ade13cfb83909d3d11d197f4 Mon Sep 17 00:00:00 2001 From: Zhihai Xu Date: Fri, 26 Jul 2013 18:10:06 +0000 Subject: Revert "Bluetooth stopped working in master - "bad file descriptor"" This reverts commit 626db853b28d64e493dd7b75073d2af838d0bc6a. Change-Id: I9ffaf5580924c150145d37ec38ffde602199b7e2 --- framework/java/android/bluetooth/BluetoothSocket.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 5c534a1e8c..d10eaea2fb 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -461,13 +461,8 @@ public final class BluetoothSocket implements Closeable { mSocket.close(); mSocket = null; } - if(mPfd != null) { - try { - mPfd.detachFd(); - } catch (IllegalArgumentException e) { - Log.w(TAG, "ignore IllegalArgumentException"); - } - } + if(mPfd != null) + mPfd.detachFd(); } } } -- cgit v1.2.3 From 008ce9e07b5e58c5ab31c5d73ec3d1ad1a6cf605 Mon Sep 17 00:00:00 2001 From: Dmitry Grinberg Date: Fri, 9 Aug 2013 15:22:59 -0700 Subject: Allow L2CAP sockets Change-Id: Icb498e6c0430789b6168bec3beb1d4650e4f1238 --- framework/java/android/bluetooth/BluetoothSocket.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d10eaea2fb..191bf67af3 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -103,6 +103,8 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int SEC_FLAG_ENCRYPT = 1; /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; + /*package*/ static final int PORT_MASK_FIXED_CHAN = 1 << 16; + private final int mType; /* one of TYPE_RFCOMM etc */ private BluetoothDevice mDevice; /* remote device */ private String mAddress; /* remote address */ @@ -115,7 +117,7 @@ public final class BluetoothSocket implements Closeable { private LocalSocket mSocket; private InputStream mSocketIS; private OutputStream mSocketOS; - private int mPort; /* RFCOMM channel or L2CAP psm */ + private int mPort; /* RFCOMM channel or L2CAP psm/channel */ private int mFd; private String mServiceName; private static int PROXY_CONNECTION_TIMEOUT = 5000; -- cgit v1.2.3 From 9cffff7bd584bf1a49298dc645aa640f2c989a54 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Wed, 2 Oct 2013 07:56:46 -0700 Subject: Revert "Allow L2CAP sockets" This reverts commit 008ce9e07b5e58c5ab31c5d73ec3d1ad1a6cf605. --- framework/java/android/bluetooth/BluetoothSocket.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 191bf67af3..d10eaea2fb 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -103,8 +103,6 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int SEC_FLAG_ENCRYPT = 1; /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; - /*package*/ static final int PORT_MASK_FIXED_CHAN = 1 << 16; - private final int mType; /* one of TYPE_RFCOMM etc */ private BluetoothDevice mDevice; /* remote device */ private String mAddress; /* remote address */ @@ -117,7 +115,7 @@ public final class BluetoothSocket implements Closeable { private LocalSocket mSocket; private InputStream mSocketIS; private OutputStream mSocketOS; - private int mPort; /* RFCOMM channel or L2CAP psm/channel */ + private int mPort; /* RFCOMM channel or L2CAP psm */ private int mFd; private String mServiceName; private static int PROXY_CONNECTION_TIMEOUT = 5000; -- cgit v1.2.3 From 9c530c2e37aa238af783db1f1715a60b4b74b02d Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Tue, 19 Nov 2013 16:54:46 -0500 Subject: Remove unused imports from frameworks/base. Change-Id: Ia1f99bd2c1105b0b0f70aa614f1f4a67b2840906 --- framework/java/android/bluetooth/BluetoothSocket.java | 5 ----- 1 file changed, 5 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d10eaea2fb..ddefc70dfd 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -16,21 +16,16 @@ package android.bluetooth; -import android.os.IBinder; import android.os.ParcelUuid; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; import java.io.Closeable; import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.List; import java.util.Locale; import java.util.UUID; import android.net.LocalSocket; -- cgit v1.2.3 From f4f4b3be361ff067ec055a1096f539c67a49b7c0 Mon Sep 17 00:00:00 2001 From: Zhihai Xu Date: Tue, 17 Dec 2013 11:39:20 -0800 Subject: NPE in BluetoothSocket.write() If calling connect succeed, we should not see this NPE. An IOException may happen after call BluetoothSocket.connect. If you still call write after the IOException, you will get this NPE. add NPE protection for possible wrong calling sequence from application, To make bluetoothSocket more error-tolerant. bug:12104154 Change-Id: I7fa4e847b500ca9b9d2a43df432f31a1bb016c0a --- .../java/android/bluetooth/BluetoothSocket.java | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d10eaea2fb..1e75fc2a1c 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -417,27 +417,28 @@ public final class BluetoothSocket implements Closeable { * if an i/o error occurs. */ /*package*/ void flush() throws IOException { + if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); if (VDBG) Log.d(TAG, "flush: " + mSocketOS); mSocketOS.flush(); } /*package*/ int read(byte[] b, int offset, int length) throws IOException { - - if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); - int ret = mSocketIS.read(b, offset, length); - if(ret < 0) - throw new IOException("bt socket closed, read return: " + ret); - if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); - return ret; + if (mSocketIS == null) throw new IOException("read is called on null InputStream"); + if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); + int ret = mSocketIS.read(b, offset, length); + if(ret < 0) + throw new IOException("bt socket closed, read return: " + ret); + if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); + return ret; } /*package*/ int write(byte[] b, int offset, int length) throws IOException { - - if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); - mSocketOS.write(b, offset, length); - // There is no good way to confirm since the entire process is asynchronous anyway - if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); - return length; + if (mSocketOS == null) throw new IOException("write is called on null OutputStream"); + if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); + mSocketOS.write(b, offset, length); + // There is no good way to confirm since the entire process is asynchronous anyway + if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); + return length; } @Override -- cgit v1.2.3 From 85c4f02c03e459009051ad706db3babecccfa5c2 Mon Sep 17 00:00:00 2001 From: Zhihai Xu Date: Tue, 17 Dec 2013 11:39:20 -0800 Subject: NPE in BluetoothSocket.write() If calling connect succeed, we should not see this NPE. An IOException may happen after call BluetoothSocket.connect. If you still call write after the IOException, you will get this NPE. add NPE protection for possible wrong calling sequence from application, To make bluetoothSocket more error-tolerant. bug:12104154 Change-Id: I7fa4e847b500ca9b9d2a43df432f31a1bb016c0a --- .../java/android/bluetooth/BluetoothSocket.java | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d10eaea2fb..1e75fc2a1c 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -417,27 +417,28 @@ public final class BluetoothSocket implements Closeable { * if an i/o error occurs. */ /*package*/ void flush() throws IOException { + if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); if (VDBG) Log.d(TAG, "flush: " + mSocketOS); mSocketOS.flush(); } /*package*/ int read(byte[] b, int offset, int length) throws IOException { - - if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); - int ret = mSocketIS.read(b, offset, length); - if(ret < 0) - throw new IOException("bt socket closed, read return: " + ret); - if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); - return ret; + if (mSocketIS == null) throw new IOException("read is called on null InputStream"); + if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); + int ret = mSocketIS.read(b, offset, length); + if(ret < 0) + throw new IOException("bt socket closed, read return: " + ret); + if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); + return ret; } /*package*/ int write(byte[] b, int offset, int length) throws IOException { - - if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); - mSocketOS.write(b, offset, length); - // There is no good way to confirm since the entire process is asynchronous anyway - if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); - return length; + if (mSocketOS == null) throw new IOException("write is called on null OutputStream"); + if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); + mSocketOS.write(b, offset, length); + // There is no good way to confirm since the entire process is asynchronous anyway + if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); + return length; } @Override -- cgit v1.2.3 From 0ad591620a446d857fbae445b5c0badf3d366c4e Mon Sep 17 00:00:00 2001 From: Zhihai Xu Date: Mon, 20 Jan 2014 12:04:23 -0800 Subject: bluetoothsocket fd leak, need close the file descriptor after detachFd. Perform ParcelFileDescriptor close after detach to avoid bluetooth socket leaks in strict mode. bug:12647433 Change-Id: I22f422547b2fb33b9bf12065dc689ed7785a7269 --- framework/java/android/bluetooth/BluetoothSocket.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 22322e338e..f532f7ce30 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -457,8 +457,10 @@ public final class BluetoothSocket implements Closeable { mSocket.close(); mSocket = null; } - if(mPfd != null) - mPfd.detachFd(); + if (mPfd != null) { + mPfd.close(); + mPfd = null; + } } } } -- cgit v1.2.3 From 8b3a52fb341f9c13b184733f1314e9374eb6c2ae Mon Sep 17 00:00:00 2001 From: Sharvil Nanavati Date: Tue, 8 Apr 2014 14:51:15 -0700 Subject: Make sure BluetoothSocket#connect throws on error. It sometimes fails silently, resulting in callers using the socket even though it hasn't been initialized. http://b/13909270 Change-Id: Ied08982b51d44c3d2dec72785888ea6c6497a664 --- framework/java/android/bluetooth/BluetoothSocket.java | 1 + 1 file changed, 1 insertion(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index f532f7ce30..00fd7ced18 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -325,6 +325,7 @@ public final class BluetoothSocket implements Closeable { } } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); + throw new IOException("unable to send RPC: " + e.getMessage()); } } -- cgit v1.2.3 From a49d75deaf8381d9b42418fec1a5202ee66c2e1d Mon Sep 17 00:00:00 2001 From: Joe LaPenna Date: Tue, 13 May 2014 18:17:46 -0700 Subject: Log accept and close debug statements in BluetoothSocket. Bug: 14902781 Bug: 14784262 Change-Id: Id0c2cd216244e05c218568427bda863a538b1041 --- .../java/android/bluetooth/BluetoothSocket.java | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 1e75fc2a1c..5738b9a6fb 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -86,8 +86,8 @@ import java.nio.ByteBuffer; */ public final class BluetoothSocket implements Closeable { private static final String TAG = "BluetoothSocket"; - private static final boolean DBG = true; - private static final boolean VDBG = false; + private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); + private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE); /** @hide */ public static final int MAX_RFCOMM_CHANNEL = 30; @@ -190,7 +190,7 @@ public final class BluetoothSocket implements Closeable { BluetoothSocket as = new BluetoothSocket(this); as.mSocketState = SocketState.CONNECTED; FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors(); - if (VDBG) Log.d(TAG, "socket fd passed by stack fds: " + fds); + if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + fds); if(fds == null || fds.length != 1) { Log.e(TAG, "socket fd passed from stack failed, fds: " + fds); as.close(); @@ -356,24 +356,24 @@ public final class BluetoothSocket implements Closeable { // read out port number try { synchronized(this) { - if (VDBG) Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + + if (DBG) Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd); if(mSocketState != SocketState.INIT) return EBADFD; if(mPfd == null) return -1; FileDescriptor fd = mPfd.getFileDescriptor(); - if (VDBG) Log.d(TAG, "bindListen(), new LocalSocket "); + if (DBG) Log.d(TAG, "bindListen(), new LocalSocket "); mSocket = new LocalSocket(fd); - if (VDBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() "); + if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() "); mSocketIS = mSocket.getInputStream(); mSocketOS = mSocket.getOutputStream(); } - if (VDBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS); + if (DBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS); int channel = readInt(mSocketIS); synchronized(this) { if(mSocketState == SocketState.INIT) mSocketState = SocketState.LISTENING; } - if (VDBG) Log.d(TAG, "channel: " + channel); + if (DBG) Log.d(TAG, "channel: " + channel); if (mPort == -1) { mPort = channel; } // else ASSERT(mPort == channel) @@ -443,7 +443,7 @@ public final class BluetoothSocket implements Closeable { @Override public void close() throws IOException { - if (VDBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState); + if (DBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState); if(mSocketState == SocketState.CLOSED) return; else @@ -453,10 +453,10 @@ public final class BluetoothSocket implements Closeable { if(mSocketState == SocketState.CLOSED) return; mSocketState = SocketState.CLOSED; - if (VDBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS + + if (DBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket); if(mSocket != null) { - if (VDBG) Log.d(TAG, "Closing mSocket: " + mSocket); + if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket); mSocket.shutdownInput(); mSocket.shutdownOutput(); mSocket.close(); -- cgit v1.2.3 From 6398bb323caca926e6d8a247eba7c1f78a796bda Mon Sep 17 00:00:00 2001 From: Matthew Xie Date: Wed, 3 Sep 2014 10:04:00 -0700 Subject: Close the base socket when bindListen fails Bug: 10773872 Change-Id: I0a72b2eb65055fa1959070d2dc32d40a573bd6f2 --- framework/java/android/bluetooth/BluetoothSocket.java | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index b98e5aed8f..36997e5448 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -375,6 +375,14 @@ public final class BluetoothSocket implements Closeable { } // else ASSERT(mPort == channel) ret = 0; } catch (IOException e) { + if (mPfd != null) { + try { + mPfd.close(); + } catch (IOException e1) { + Log.e(TAG, "bindListen, close mPfd: " + e1); + } + mPfd = null; + } Log.e(TAG, "bindListen, fail to get port number, exception: " + e); return -1; } -- cgit v1.2.3 From c0a7c93812c39589a1c90a18c93ddb3a4e36205a Mon Sep 17 00:00:00 2001 From: Casper Bonde Date: Thu, 9 Apr 2015 09:24:48 +0200 Subject: OBEX Over L2CAP + SDP search API for BT profiles - Updated OBEX to support SRM - Added support for OBEX over l2cap and SRM. - Minor bugfixes, and reduce CPU load ALOT - Added support to send responses without body data. - Extend BluetoothSocket to support L2CAP - Added functionality to get the channel number needed to be able to create an SDP record with the channel number. - Added interface to get socket type and max packet sizes. - Added interface to perform SDP search and get the resulting SDP record data. Change-Id: I9d37a00ce73dfffc0e3ce03eab5511ba3a86e5b8 --- .../java/android/bluetooth/BluetoothSocket.java | 197 ++++++++++++++++++--- 1 file changed, 173 insertions(+), 24 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 36997e5448..5702d117b6 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -21,6 +21,7 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; +import java.io.BufferedInputStream; import java.io.Closeable; import java.io.FileDescriptor; import java.io.IOException; @@ -29,6 +30,8 @@ import java.io.OutputStream; import java.util.Locale; import java.util.UUID; import android.net.LocalSocket; + +import java.nio.Buffer; import java.nio.ByteOrder; import java.nio.ByteBuffer; /** @@ -86,17 +89,19 @@ public final class BluetoothSocket implements Closeable { /** @hide */ public static final int MAX_RFCOMM_CHANNEL = 30; + /*package*/ static final int MAX_L2CAP_PACKAGE_SIZE = 0xFFFF; /** Keep TYPE_ fields in sync with BluetoothSocket.cpp */ - /*package*/ static final int TYPE_RFCOMM = 1; - /*package*/ static final int TYPE_SCO = 2; - /*package*/ static final int TYPE_L2CAP = 3; + public static final int TYPE_RFCOMM = 1; + public static final int TYPE_SCO = 2; + public static final int TYPE_L2CAP = 3; /*package*/ static final int EBADFD = 77; /*package*/ static final int EADDRINUSE = 98; /*package*/ static final int SEC_FLAG_ENCRYPT = 1; /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; + /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2; private final int mType; /* one of TYPE_RFCOMM etc */ private BluetoothDevice mDevice; /* remote device */ @@ -106,6 +111,7 @@ public final class BluetoothSocket implements Closeable { private final BluetoothInputStream mInputStream; private final BluetoothOutputStream mOutputStream; private final ParcelUuid mUuid; + private boolean mExcludeSdp = false; private ParcelFileDescriptor mPfd; private LocalSocket mSocket; private InputStream mSocketIS; @@ -115,7 +121,11 @@ public final class BluetoothSocket implements Closeable { private String mServiceName; private static int PROXY_CONNECTION_TIMEOUT = 5000; - private static int SOCK_SIGNAL_SIZE = 16; + private static int SOCK_SIGNAL_SIZE = 20; + + private ByteBuffer mL2capBuffer = null; + private int mMaxTxPacketSize = 0; // The l2cap maximum packet size supported by the peer. + private int mMaxRxPacketSize = 0; // The l2cap maximum packet size that can be received. private enum SocketState { INIT, @@ -144,12 +154,14 @@ public final class BluetoothSocket implements Closeable { */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid) throws IOException { - if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1) { + if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type); + if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1 + && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { if (port < 1 || port > MAX_RFCOMM_CHANNEL) { throw new IOException("Invalid RFCOMM channel: " + port); } } - if(uuid != null) + if (uuid != null) mUuid = uuid; else mUuid = new ParcelUuid(new UUID(0, 0)); mType = type; @@ -172,6 +184,7 @@ public final class BluetoothSocket implements Closeable { mOutputStream = new BluetoothOutputStream(this); } private BluetoothSocket(BluetoothSocket s) { + if (VDBG) Log.d(TAG, "Creating new Private BluetoothSocket of type: " + s.mType); mUuid = s.mUuid; mType = s.mType; mAuth = s.mAuth; @@ -179,7 +192,11 @@ public final class BluetoothSocket implements Closeable { mPort = s.mPort; mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); + mMaxRxPacketSize = s.mMaxRxPacketSize; + mMaxTxPacketSize = s.mMaxTxPacketSize; + mServiceName = s.mServiceName; + mExcludeSdp = s.mExcludeSdp; } private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException { BluetoothSocket as = new BluetoothSocket(this); @@ -229,6 +246,8 @@ public final class BluetoothSocket implements Closeable { flags |= SEC_FLAG_AUTH; if(mEncrypt) flags |= SEC_FLAG_ENCRYPT; + if(mExcludeSdp) + flags |= BTSOCK_FLAG_NO_SDP; return flags; } @@ -298,7 +317,8 @@ public final class BluetoothSocket implements Closeable { try { if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); - IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + IBluetooth bluetoothProxy = + BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); if (bluetoothProxy == null) throw new IOException("Bluetooth is off"); mPfd = bluetoothProxy.connectSocket(mDevice, mType, mUuid, mPort, getSecurityFlags()); @@ -370,7 +390,7 @@ public final class BluetoothSocket implements Closeable { mSocketState = SocketState.LISTENING; } if (DBG) Log.d(TAG, "channel: " + channel); - if (mPort == -1) { + if (mPort <= -1) { mPort = channel; } // else ASSERT(mPort == channel) ret = 0; @@ -391,7 +411,8 @@ public final class BluetoothSocket implements Closeable { /*package*/ BluetoothSocket accept(int timeout) throws IOException { BluetoothSocket acceptedSocket; - if (mSocketState != SocketState.LISTENING) throw new IOException("bt socket is not in listen state"); + if (mSocketState != SocketState.LISTENING) + throw new IOException("bt socket is not in listen state"); if(timeout > 0) { Log.d(TAG, "accept() set timeout (ms):" + timeout); mSocket.setSoTimeout(timeout); @@ -427,27 +448,80 @@ public final class BluetoothSocket implements Closeable { } /*package*/ int read(byte[] b, int offset, int length) throws IOException { - if (mSocketIS == null) throw new IOException("read is called on null InputStream"); + int ret = 0; if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); - int ret = mSocketIS.read(b, offset, length); - if(ret < 0) + if(mType == TYPE_L2CAP) + { + int bytesToRead = length; + if (VDBG) Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length + + "mL2capBuffer= " + mL2capBuffer); + if (mL2capBuffer == null) { + createL2capRxBuffer(); + } + if (mL2capBuffer.remaining() == 0) { + if (VDBG) Log.v(TAG, "l2cap buffer empty, refilling..."); + if (fillL2capRxBuffer() == -1) { + return -1; + } + } + if (bytesToRead > mL2capBuffer.remaining()) { + bytesToRead = mL2capBuffer.remaining(); + } + if(VDBG) Log.v(TAG, "get(): offset: " + offset + + " bytesToRead: " + bytesToRead); + mL2capBuffer.get(b, offset, bytesToRead); + ret = bytesToRead; + }else { + if (VDBG) Log.v(TAG, "default: read(): offset: " + offset + " length:" + length); + ret = mSocketIS.read(b, offset, length); + } + if (ret < 0) throw new IOException("bt socket closed, read return: " + ret); if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); return ret; } /*package*/ int write(byte[] b, int offset, int length) throws IOException { - if (mSocketOS == null) throw new IOException("write is called on null OutputStream"); - if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); - mSocketOS.write(b, offset, length); - // There is no good way to confirm since the entire process is asynchronous anyway - if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); - return length; + + //TODO: Since bindings can exist between the SDU size and the + // protocol, we might need to throw an exception instead of just + // splitting the write into multiple smaller writes. + // Rfcomm uses dynamic allocation, and should not have any bindings + // to the actual message length. + if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); + if (mType == TYPE_L2CAP) { + if(length <= mMaxTxPacketSize) { + mSocketOS.write(b, offset, length); + } else { + int tmpOffset = offset; + int tmpLength = mMaxTxPacketSize; + int endIndex = offset + length; + boolean done = false; + if(DBG) Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n" + + "Packet will be divided into SDU packets of size " + + mMaxTxPacketSize); + do{ + mSocketOS.write(b, tmpOffset, tmpLength); + tmpOffset += mMaxTxPacketSize; + if((tmpOffset + mMaxTxPacketSize) > endIndex) { + tmpLength = endIndex - tmpOffset; + done = true; + } + } while(!done); + + } + } else { + mSocketOS.write(b, offset, length); + } + // There is no good way to confirm since the entire process is asynchronous anyway + if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); + return length; } @Override public void close() throws IOException { - if (DBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState); + if (DBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + + mSocketState); if(mSocketState == SocketState.CLOSED) return; else @@ -457,8 +531,9 @@ public final class BluetoothSocket implements Closeable { if(mSocketState == SocketState.CLOSED) return; mSocketState = SocketState.CLOSED; - if (DBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS + - ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket); + if (DBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort + + ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + + "mSocket: " + mSocket); if(mSocket != null) { if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket); mSocket.shutdownInput(); @@ -480,6 +555,47 @@ public final class BluetoothSocket implements Closeable { /*package */ int getPort() { return mPort; } + + /** + * Get the maximum supported Transmit packet size for the underlying transport. + * Use this to optimize the writes done to the output socket, to avoid sending + * half full packets. + * @return the maximum supported Transmit packet size for the underlying transport. + */ + public int getMaxTransmitPacketSize(){ + return mMaxTxPacketSize; + } + + /** + * Get the maximum supported Receive packet size for the underlying transport. + * Use this to optimize the reads done on the input stream, as any call to read + * will return a maximum of this amount of bytes - or for some transports a + * multiple of this value. + * @return the maximum supported Receive packet size for the underlying transport. + */ + public int getMaxReceivePacketSize(){ + return mMaxRxPacketSize; + } + + /** + * Get the type of the underlying connection + * @return one of TYPE_ + */ + public int getConnectionType() { + return mType; + } + + /** + * Change if a SDP entry should be automatically created. + * Must be called before calling .bind, for the call to have any effect. + * @param mExcludeSdp

  • TRUE - do not auto generate SDP record. + *
  • FALSE - default - auto generate SPP SDP record. + * @hide + */ + public void setExcludeSdp(boolean excludeSdp) { + this.mExcludeSdp = excludeSdp; + } + private String convertAddr(final byte[] addr) { return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0] , addr[1], addr[2], addr[3] , addr[4], addr[5]); @@ -487,8 +603,10 @@ public final class BluetoothSocket implements Closeable { private String waitSocketSignal(InputStream is) throws IOException { byte [] sig = new byte[SOCK_SIGNAL_SIZE]; int ret = readAll(is, sig); - if (VDBG) Log.d(TAG, "waitSocketSignal read 16 bytes signal ret: " + ret); + if (VDBG) Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + + " bytes signal ret: " + ret); ByteBuffer bb = ByteBuffer.wrap(sig); + /* the struct in native is decorated with __attribute__((packed)), hence this is possible */ bb.order(ByteOrder.nativeOrder()); int size = bb.getShort(); if(size != SOCK_SIGNAL_SIZE) @@ -497,19 +615,36 @@ public final class BluetoothSocket implements Closeable { bb.get(addr); int channel = bb.getInt(); int status = bb.getInt(); + mMaxTxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value + mMaxRxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value String RemoteAddr = convertAddr(addr); if (VDBG) Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: " - + RemoteAddr + ", channel: " + channel + ", status: " + status); + + RemoteAddr + ", channel: " + channel + ", status: " + status + + " MaxRxPktSize: " + mMaxRxPacketSize + " MaxTxPktSize: " + mMaxTxPacketSize); if(status != 0) throw new IOException("Connection failure, status: " + status); return RemoteAddr; } + + private void createL2capRxBuffer(){ + if(mType == TYPE_L2CAP) { + // Allocate the buffer to use for reads. + if(VDBG) Log.v(TAG, " Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize); + mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]); + if(VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining()); + mL2capBuffer.limit(0); // Ensure we do a real read at the first read-request + if(VDBG) Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + + mL2capBuffer.remaining()); + } + } + private int readAll(InputStream is, byte[] b) throws IOException { int left = b.length; while(left > 0) { int ret = is.read(b, b.length - left, left); if(ret <= 0) - throw new IOException("read failed, socket might closed or timeout, read ret: " + ret); + throw new IOException("read failed, socket might closed or timeout, read ret: " + + ret); left -= ret; if(left != 0) Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) + @@ -526,4 +661,18 @@ public final class BluetoothSocket implements Closeable { bb.order(ByteOrder.nativeOrder()); return bb.getInt(); } + + private int fillL2capRxBuffer() throws IOException { + mL2capBuffer.rewind(); + int ret = mSocketIS.read(mL2capBuffer.array()); + if(ret == -1) { + // reached end of stream - return -1 + mL2capBuffer.limit(0); + return -1; + } + mL2capBuffer.limit(ret); + return ret; + } + + } -- cgit v1.2.3 From 660bff7dedcab83606ca69560bf4bcd003e1c7e7 Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Mon, 4 May 2015 13:48:50 -0700 Subject: Add documentation for BluetoothSocket.getConnectionType() Bug: 20824264 Change-Id: I58aa8f5bbe08ddb252f01f4ad187ae8741963f0b --- framework/java/android/bluetooth/BluetoothSocket.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 5702d117b6..5cf2300bef 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -91,9 +91,13 @@ public final class BluetoothSocket implements Closeable { public static final int MAX_RFCOMM_CHANNEL = 30; /*package*/ static final int MAX_L2CAP_PACKAGE_SIZE = 0xFFFF; - /** Keep TYPE_ fields in sync with BluetoothSocket.cpp */ + /** RFCOMM socket */ public static final int TYPE_RFCOMM = 1; + + /** SCO socket */ public static final int TYPE_SCO = 2; + + /** L2CAP socket */ public static final int TYPE_L2CAP = 3; /*package*/ static final int EBADFD = 77; @@ -578,8 +582,8 @@ public final class BluetoothSocket implements Closeable { } /** - * Get the type of the underlying connection - * @return one of TYPE_ + * Get the type of the underlying connection. + * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP} */ public int getConnectionType() { return mType; -- cgit v1.2.3 From 60d77c2c9ceea76d7e4e32ab173ef3da64ff607e Mon Sep 17 00:00:00 2001 From: Casper Bonde Date: Tue, 21 Apr 2015 13:12:05 +0200 Subject: Add support for MITM for BluetoothSockets (1/4) This change adds an option to enforce Man-in-the-middle protection for the authentication process. This feature is needed for the Sim Access Profile. Change-Id: Ia3ef0caeb750f88608c9fa6bf6367d1c77de4cf3 Signed-off-by: Casper Bonde --- .../java/android/bluetooth/BluetoothSocket.java | 28 ++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 5cf2300bef..6ca6976b9a 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -106,6 +106,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int SEC_FLAG_ENCRYPT = 1; /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2; + /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3; private final int mType; /* one of TYPE_RFCOMM etc */ private BluetoothDevice mDevice; /* remote device */ @@ -115,7 +116,8 @@ public final class BluetoothSocket implements Closeable { private final BluetoothInputStream mInputStream; private final BluetoothOutputStream mOutputStream; private final ParcelUuid mUuid; - private boolean mExcludeSdp = false; + private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */ + private boolean mAuthMitm = false; /* when true Man-in-the-middle protection will be enabled*/ private ParcelFileDescriptor mPfd; private LocalSocket mSocket; private InputStream mSocketIS; @@ -158,6 +160,24 @@ public final class BluetoothSocket implements Closeable { */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid) throws IOException { + this(type, fd, auth, encrypt, device, port, uuid, false); + } + + /** + * Construct a BluetoothSocket. + * @param type type of socket + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated + * @param encrypt require the connection to be encrypted + * @param device remote device that this socket can connect to + * @param port remote port + * @param uuid SDP uuid + * @param mitm enforce man-in-the-middle protection. + * @throws IOException On error, for example Bluetooth not available, or + * insufficient privileges + */ + /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, + BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm) throws IOException { if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type); if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1 && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { @@ -170,6 +190,7 @@ public final class BluetoothSocket implements Closeable { else mUuid = new ParcelUuid(new UUID(0, 0)); mType = type; mAuth = auth; + mAuthMitm = mitm; mEncrypt = encrypt; mDevice = device; mPort = port; @@ -201,6 +222,7 @@ public final class BluetoothSocket implements Closeable { mServiceName = s.mServiceName; mExcludeSdp = s.mExcludeSdp; + mAuthMitm = s.mAuthMitm; } private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException { BluetoothSocket as = new BluetoothSocket(this); @@ -232,7 +254,7 @@ public final class BluetoothSocket implements Closeable { */ private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port) throws IOException { - this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null); + this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null, false); } /** @hide */ @@ -252,6 +274,8 @@ public final class BluetoothSocket implements Closeable { flags |= SEC_FLAG_ENCRYPT; if(mExcludeSdp) flags |= BTSOCK_FLAG_NO_SDP; + if(mAuthMitm) + flags |= SEC_FLAG_AUTH_MITM; return flags; } -- cgit v1.2.3 From 91276018bd5dd6c61dcd69cd87090ba022b532e7 Mon Sep 17 00:00:00 2001 From: Casper Bonde Date: Fri, 8 May 2015 14:32:24 +0200 Subject: SAP: Make it possible to enforce a 16-digit pin code (4/5) This change enable the posibility to enforce using a 16-digit pin or MITM for a RFCOMM or L2CAP connection. This is needed for the SIM access profile. Change-Id: I3205013f9e758c353381442a86845dab467780f8 Signed-off-by: Casper Bonde --- framework/java/android/bluetooth/BluetoothSocket.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 6ca6976b9a..6302521e63 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -107,6 +107,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2; /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3; + /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4; private final int mType; /* one of TYPE_RFCOMM etc */ private BluetoothDevice mDevice; /* remote device */ @@ -118,6 +119,7 @@ public final class BluetoothSocket implements Closeable { private final ParcelUuid mUuid; private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */ private boolean mAuthMitm = false; /* when true Man-in-the-middle protection will be enabled*/ + private boolean mMin16DigitPin = false; /* Minimum 16 digit pin for sec mode 2 connections */ private ParcelFileDescriptor mPfd; private LocalSocket mSocket; private InputStream mSocketIS; @@ -160,7 +162,7 @@ public final class BluetoothSocket implements Closeable { */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid) throws IOException { - this(type, fd, auth, encrypt, device, port, uuid, false); + this(type, fd, auth, encrypt, device, port, uuid, false, false); } /** @@ -173,11 +175,13 @@ public final class BluetoothSocket implements Closeable { * @param port remote port * @param uuid SDP uuid * @param mitm enforce man-in-the-middle protection. + * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection * @throws IOException On error, for example Bluetooth not available, or * insufficient privileges */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, - BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm) throws IOException { + BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin) + throws IOException { if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type); if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1 && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { @@ -191,6 +195,7 @@ public final class BluetoothSocket implements Closeable { mType = type; mAuth = auth; mAuthMitm = mitm; + mMin16DigitPin = min16DigitPin; mEncrypt = encrypt; mDevice = device; mPort = port; @@ -223,6 +228,7 @@ public final class BluetoothSocket implements Closeable { mServiceName = s.mServiceName; mExcludeSdp = s.mExcludeSdp; mAuthMitm = s.mAuthMitm; + mMin16DigitPin = s.mMin16DigitPin; } private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException { BluetoothSocket as = new BluetoothSocket(this); @@ -254,7 +260,7 @@ public final class BluetoothSocket implements Closeable { */ private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port) throws IOException { - this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null, false); + this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null, false, false); } /** @hide */ @@ -276,6 +282,8 @@ public final class BluetoothSocket implements Closeable { flags |= BTSOCK_FLAG_NO_SDP; if(mAuthMitm) flags |= SEC_FLAG_AUTH_MITM; + if(mMin16DigitPin) + flags |= SEC_FLAG_AUTH_16_DIGIT; return flags; } -- cgit v1.2.3 From c6242459415fe6bd92aa1e0d69dd63edb339f7b7 Mon Sep 17 00:00:00 2001 From: Zach Johnson Date: Mon, 13 Jul 2015 18:00:35 -0700 Subject: Fix BluetoothSocket file descriptor leak Sockets accepted on a server socket didn't populate the mPfd field, which is used to close out the java end of the native-and-java communication socket when the overall rfcomm socket is closed. #badnewsbears b/21398841 Change-Id: I3adb0a9965f83d0f3006fa4f79ea4abeab5c9a17 --- framework/java/android/bluetooth/BluetoothSocket.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 6302521e63..fb81fd1ea9 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -240,6 +240,8 @@ public final class BluetoothSocket implements Closeable { as.close(); throw new IOException("bt socket acept failed"); } + + as.mPfd = new ParcelFileDescriptor(fds[0]); as.mSocket = new LocalSocket(fds[0]); as.mSocketIS = as.mSocket.getInputStream(); as.mSocketOS = as.mSocket.getOutputStream(); -- cgit v1.2.3 From 7b1e740c286aeea6a38d8f95ccb30d16ff599a19 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Fri, 11 Dec 2015 18:00:38 -0800 Subject: Frameworks/base: Use Arrays.toString Fix a couple of cases where Arrays.toString should be used. Bug: 19797138 Change-Id: I905fc79e63face9b26975320a92086c732bf6316 --- framework/java/android/bluetooth/BluetoothSocket.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index fb81fd1ea9..ae12c88ff2 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -27,6 +27,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Arrays; import java.util.Locale; import java.util.UUID; import android.net.LocalSocket; @@ -234,9 +235,9 @@ public final class BluetoothSocket implements Closeable { BluetoothSocket as = new BluetoothSocket(this); as.mSocketState = SocketState.CONNECTED; FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors(); - if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + fds); + if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + Arrays.toString(fds)); if(fds == null || fds.length != 1) { - Log.e(TAG, "socket fd passed from stack failed, fds: " + fds); + Log.e(TAG, "socket fd passed from stack failed, fds: " + Arrays.toString(fds)); as.close(); throw new IOException("bt socket acept failed"); } -- cgit v1.2.3 From 5822d7e47b82cf951a758785754b474e487a0388 Mon Sep 17 00:00:00 2001 From: Christine Hallstrom Date: Fri, 17 Jun 2016 16:00:25 -0700 Subject: Fix early termination of while loop in BluetoothSocket#write While loop exits too early and misses writing remaining bytes. Also restructured the loop itself to be more readable. Change-Id: I71e9b331d20b5ae70175450c3346be43ab56c40c --- .../java/android/bluetooth/BluetoothSocket.java | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index ae12c88ff2..ec01beff93 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -532,22 +532,19 @@ public final class BluetoothSocket implements Closeable { if(length <= mMaxTxPacketSize) { mSocketOS.write(b, offset, length); } else { - int tmpOffset = offset; - int tmpLength = mMaxTxPacketSize; - int endIndex = offset + length; - boolean done = false; if(DBG) Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n" + "Packet will be divided into SDU packets of size " + mMaxTxPacketSize); - do{ + int tmpOffset = offset; + int bytesToWrite = length; + while (bytesToWrite > 0) { + int tmpLength = (bytesToWrite > mMaxTxPacketSize) + ? mMaxTxPacketSize + : bytesToWrite; mSocketOS.write(b, tmpOffset, tmpLength); - tmpOffset += mMaxTxPacketSize; - if((tmpOffset + mMaxTxPacketSize) > endIndex) { - tmpLength = endIndex - tmpOffset; - done = true; - } - } while(!done); - + tmpOffset += tmpLength; + bytesToWrite -= tmpLength; + } } } else { mSocketOS.write(b, offset, length); -- cgit v1.2.3 From f242df2f7ac42405d7d4d83bb745c2bc40088c13 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Mon, 20 Jun 2016 10:26:31 -0700 Subject: Fix links to Bluetooth Guide Change-Id: I5798c3d71c7cc9c509e0f7b04fa140168b0fdc11 --- framework/java/android/bluetooth/BluetoothSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index fb81fd1ea9..07ec9df0ea 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -75,7 +75,7 @@ import java.nio.ByteBuffer; *
    *

    Developer Guides

    *

    For more information about using Bluetooth, read the - * Bluetooth developer guide.

    + * Bluetooth developer guide.

    *
    * * {@see BluetoothServerSocket} -- cgit v1.2.3 From 3dfe08b1ceefb805341b04c48ec9f8f460f47a65 Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Fri, 6 Jan 2017 11:29:15 +0000 Subject: Refactor RFCOMM / BluetoothSocket usage of LocalSocket LocalSocket is used by BluetoothSocket. BluetoothSocket passes a pre-created file descriptor to LocalSocket that is then given to the LocalSocketImpl. Commit b08c7bc0bdc48ae95be2697ca27ea89a9dd92c3e broke the behavior. Commit 7a8c36aa4e6a1b5e48f0ee5a787f10bcfece7587 put in a minimal fix. This change tidies up LocalSocket and associated classes and replaces a specialist constructor with a factory method to highlight the special case. While there an unnecessary exception has been removed. Bug: 34111534 Test: Boot device Test: vogar --mode app_process tests/tests/net/src/android/net/cts/LocalSocketTest.java Change-Id: I4ba2f2d9ea361a950ff8bc8d64fc800d998c3210 --- framework/java/android/bluetooth/BluetoothSocket.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index b68693880a..98a5341b30 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -243,7 +243,7 @@ public final class BluetoothSocket implements Closeable { } as.mPfd = new ParcelFileDescriptor(fds[0]); - as.mSocket = new LocalSocket(fds[0]); + as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]); as.mSocketIS = as.mSocket.getInputStream(); as.mSocketOS = as.mSocket.getOutputStream(); as.mAddress = RemoteAddr; @@ -367,7 +367,7 @@ public final class BluetoothSocket implements Closeable { if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); if (mPfd == null) throw new IOException("bt socket connect failed"); FileDescriptor fd = mPfd.getFileDescriptor(); - mSocket = new LocalSocket(fd); + mSocket = LocalSocket.createConnectedLocalSocket(fd); mSocketIS = mSocket.getInputStream(); mSocketOS = mSocket.getOutputStream(); } @@ -416,9 +416,9 @@ public final class BluetoothSocket implements Closeable { if(mSocketState != SocketState.INIT) return EBADFD; if(mPfd == null) return -1; FileDescriptor fd = mPfd.getFileDescriptor(); - if (DBG) Log.d(TAG, "bindListen(), new LocalSocket "); - mSocket = new LocalSocket(fd); - if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() "); + if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket"); + mSocket = LocalSocket.createConnectedLocalSocket(fd); + if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()"); mSocketIS = mSocket.getInputStream(); mSocketOS = mSocket.getOutputStream(); } -- cgit v1.2.3 From 178b028531db3a15866ff9dba6b875610f6ecbe3 Mon Sep 17 00:00:00 2001 From: Ajay Panicker Date: Tue, 28 Mar 2017 14:28:27 -0700 Subject: Bluetooth: Add additional BluetoothSocket logging to root cause errors Bug: 34780400 Test: Code still compiles Change-Id: I166842ecc6889f9ea403e7aa3678ed818cd80968 --- framework/java/android/bluetooth/BluetoothSocket.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 98a5341b30..6bf6aa0a9e 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -416,6 +416,11 @@ public final class BluetoothSocket implements Closeable { if(mSocketState != SocketState.INIT) return EBADFD; if(mPfd == null) return -1; FileDescriptor fd = mPfd.getFileDescriptor(); + if (fd == null) { + Log.e(TAG, "bindListen(), null file descriptor"); + return -1; + } + if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket"); mSocket = LocalSocket.createConnectedLocalSocket(fd); if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()"); @@ -556,8 +561,9 @@ public final class BluetoothSocket implements Closeable { @Override public void close() throws IOException { - if (DBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " - + mSocketState); + Log.d(TAG, "close() this: " + this + ", channel: " + mPort + + ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + + "mSocket: " + mSocket + ", mSocketState: " + mSocketState); if(mSocketState == SocketState.CLOSED) return; else @@ -567,9 +573,6 @@ public final class BluetoothSocket implements Closeable { if(mSocketState == SocketState.CLOSED) return; mSocketState = SocketState.CLOSED; - if (DBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort + - ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + - "mSocket: " + mSocket); if(mSocket != null) { if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket); mSocket.shutdownInput(); -- cgit v1.2.3 From 910201beb0bde1dcf6b33e4ec5d1eb60042419d8 Mon Sep 17 00:00:00 2001 From: Jack He Date: Tue, 22 Aug 2017 16:06:54 -0700 Subject: Fix checkstyle errors (1/2) * Automatic style corrections through IDE Bug: 63596319 Test: make checkbuild, no manual changes, no functional changes Change-Id: I2397d55abc34c9b7a9b748bec6137778df3421a7 --- .../java/android/bluetooth/BluetoothSocket.java | 308 ++++++++++++--------- 1 file changed, 175 insertions(+), 133 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 6bf6aa0a9e..a90dd82b96 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -16,25 +16,23 @@ package android.bluetooth; -import android.os.ParcelUuid; +import android.net.LocalSocket; import android.os.ParcelFileDescriptor; +import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; -import java.io.BufferedInputStream; import java.io.Closeable; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.Arrays; import java.util.Locale; import java.util.UUID; -import android.net.LocalSocket; -import java.nio.Buffer; -import java.nio.ByteOrder; -import java.nio.ByteBuffer; /** * A connected or connecting Bluetooth socket. * @@ -106,9 +104,9 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int SEC_FLAG_ENCRYPT = 1; /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; - /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2; - /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3; - /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4; + /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2; + /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3; + /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4; private final int mType; /* one of TYPE_RFCOMM etc */ private BluetoothDevice mDevice; /* remote device */ @@ -151,15 +149,16 @@ public final class BluetoothSocket implements Closeable { /** * Construct a BluetoothSocket. - * @param type type of socket - * @param fd fd to use for connected socket, or -1 for a new socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param device remote device that this socket can connect to - * @param port remote port - * @param uuid SDP uuid - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @param device remote device that this socket can connect to + * @param port remote port + * @param uuid SDP uuid + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid) throws IOException { @@ -168,21 +167,22 @@ public final class BluetoothSocket implements Closeable { /** * Construct a BluetoothSocket. - * @param type type of socket - * @param fd fd to use for connected socket, or -1 for a new socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param device remote device that this socket can connect to - * @param port remote port - * @param uuid SDP uuid - * @param mitm enforce man-in-the-middle protection. + * @param device remote device that this socket can connect to + * @param port remote port + * @param uuid SDP uuid + * @param mitm enforce man-in-the-middle protection. * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin) - throws IOException { + throws IOException { if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type); if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1 && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { @@ -190,9 +190,11 @@ public final class BluetoothSocket implements Closeable { throw new IOException("Invalid RFCOMM channel: " + port); } } - if (uuid != null) + if (uuid != null) { mUuid = uuid; - else mUuid = new ParcelUuid(new UUID(0, 0)); + } else { + mUuid = new ParcelUuid(new UUID(0, 0)); + } mType = type; mAuth = auth; mAuthMitm = mitm; @@ -214,6 +216,7 @@ public final class BluetoothSocket implements Closeable { mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); } + private BluetoothSocket(BluetoothSocket s) { if (VDBG) Log.d(TAG, "Creating new Private BluetoothSocket of type: " + s.mType); mUuid = s.mUuid; @@ -231,12 +234,13 @@ public final class BluetoothSocket implements Closeable { mAuthMitm = s.mAuthMitm; mMin16DigitPin = s.mMin16DigitPin; } + private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException { BluetoothSocket as = new BluetoothSocket(this); as.mSocketState = SocketState.CONNECTED; FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors(); if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + Arrays.toString(fds)); - if(fds == null || fds.length != 1) { + if (fds == null || fds.length != 1) { Log.e(TAG, "socket fd passed from stack failed, fds: " + Arrays.toString(fds)); as.close(); throw new IOException("bt socket acept failed"); @@ -250,16 +254,18 @@ public final class BluetoothSocket implements Closeable { as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(RemoteAddr); return as; } + /** * Construct a BluetoothSocket from address. Used by native code. - * @param type type of socket - * @param fd fd to use for connected socket, or -1 for a new socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted * @param address remote device that this socket can connect to - * @param port remote port - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @param port remote port + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port) throws IOException { @@ -275,23 +281,30 @@ public final class BluetoothSocket implements Closeable { super.finalize(); } } + private int getSecurityFlags() { int flags = 0; - if(mAuth) + if (mAuth) { flags |= SEC_FLAG_AUTH; - if(mEncrypt) + } + if (mEncrypt) { flags |= SEC_FLAG_ENCRYPT; - if(mExcludeSdp) + } + if (mExcludeSdp) { flags |= BTSOCK_FLAG_NO_SDP; - if(mAuthMitm) + } + if (mAuthMitm) { flags |= SEC_FLAG_AUTH_MITM; - if(mMin16DigitPin) + } + if (mMin16DigitPin) { flags |= SEC_FLAG_AUTH_16_DIGIT; + } return flags; } /** * Get the remote device this socket is connecting, or connected, to. + * * @return remote device */ public BluetoothDevice getRemoteDevice() { @@ -303,6 +316,7 @@ public final class BluetoothSocket implements Closeable { *

    The input stream will be returned even if the socket is not yet * connected, but operations on that stream will throw IOException until * the associated socket is connected. + * * @return InputStream */ public InputStream getInputStream() throws IOException { @@ -314,6 +328,7 @@ public final class BluetoothSocket implements Closeable { *

    The output stream will be returned even if the socket is not yet * connected, but operations on that stream will throw IOException until * the associated socket is connected. + * * @return OutputStream */ public OutputStream getOutputStream() throws IOException { @@ -323,8 +338,8 @@ public final class BluetoothSocket implements Closeable { /** * Get the connection status of this socket, ie, whether there is an active connection with * remote device. - * @return true if connected - * false if not connected + * + * @return true if connected false if not connected */ public boolean isConnected() { return mSocketState == SocketState.CONNECTED; @@ -349,6 +364,7 @@ public final class BluetoothSocket implements Closeable { * {@link BluetoothAdapter#cancelDiscovery()} even if it * did not directly request a discovery, just to be sure. *

    {@link #close} can be used to abort this call from another thread. + * * @throws IOException on error, for example connection failure */ public void connect() throws IOException { @@ -361,8 +377,7 @@ public final class BluetoothSocket implements Closeable { if (bluetoothProxy == null) throw new IOException("Bluetooth is off"); mPfd = bluetoothProxy.connectSocket(mDevice, mType, mUuid, mPort, getSecurityFlags()); - synchronized(this) - { + synchronized (this) { if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd); if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); if (mPfd == null) throw new IOException("bt socket connect failed"); @@ -372,14 +387,15 @@ public final class BluetoothSocket implements Closeable { mSocketOS = mSocket.getOutputStream(); } int channel = readInt(mSocketIS); - if (channel <= 0) + if (channel <= 0) { throw new IOException("bt socket connect failed"); + } mPort = channel; waitSocketSignal(mSocketIS); - synchronized(this) - { - if (mSocketState == SocketState.CLOSED) + synchronized (this) { + if (mSocketState == SocketState.CLOSED) { throw new IOException("bt socket closed"); + } mSocketState = SocketState.CONNECTED; } } catch (RemoteException e) { @@ -410,11 +426,13 @@ public final class BluetoothSocket implements Closeable { // read out port number try { - synchronized(this) { - if (DBG) Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + - mPfd); - if(mSocketState != SocketState.INIT) return EBADFD; - if(mPfd == null) return -1; + synchronized (this) { + if (DBG) { + Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + + mPfd); + } + if (mSocketState != SocketState.INIT) return EBADFD; + if (mPfd == null) return -1; FileDescriptor fd = mPfd.getFileDescriptor(); if (fd == null) { Log.e(TAG, "bindListen(), null file descriptor"); @@ -429,9 +447,10 @@ public final class BluetoothSocket implements Closeable { } if (DBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS); int channel = readInt(mSocketIS); - synchronized(this) { - if(mSocketState == SocketState.INIT) + synchronized (this) { + if (mSocketState == SocketState.INIT) { mSocketState = SocketState.LISTENING; + } } if (DBG) Log.d(TAG, "channel: " + channel); if (mPort <= -1) { @@ -455,19 +474,21 @@ public final class BluetoothSocket implements Closeable { /*package*/ BluetoothSocket accept(int timeout) throws IOException { BluetoothSocket acceptedSocket; - if (mSocketState != SocketState.LISTENING) + if (mSocketState != SocketState.LISTENING) { throw new IOException("bt socket is not in listen state"); - if(timeout > 0) { + } + if (timeout > 0) { Log.d(TAG, "accept() set timeout (ms):" + timeout); - mSocket.setSoTimeout(timeout); + mSocket.setSoTimeout(timeout); } String RemoteAddr = waitSocketSignal(mSocketIS); - if(timeout > 0) + if (timeout > 0) { mSocket.setSoTimeout(0); - synchronized(this) - { - if (mSocketState != SocketState.LISTENING) + } + synchronized (this) { + if (mSocketState != SocketState.LISTENING) { throw new IOException("bt socket is not in listen state"); + } acceptedSocket = acceptSocket(RemoteAddr); //quick drop the reference of the file handle } @@ -478,12 +499,13 @@ public final class BluetoothSocket implements Closeable { if (VDBG) Log.d(TAG, "available: " + mSocketIS); return mSocketIS.available(); } + /** * Wait until the data in sending queue is emptied. A polling version * for flush implementation. Used to ensure the writing data afterwards will * be packed in new RFCOMM frame. - * @throws IOException - * if an i/o error occurs. + * + * @throws IOException if an i/o error occurs. */ /*package*/ void flush() throws IOException { if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); @@ -494,11 +516,12 @@ public final class BluetoothSocket implements Closeable { /*package*/ int read(byte[] b, int offset, int length) throws IOException { int ret = 0; if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); - if(mType == TYPE_L2CAP) - { + if (mType == TYPE_L2CAP) { int bytesToRead = length; - if (VDBG) Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length - + "mL2capBuffer= " + mL2capBuffer); + if (VDBG) { + Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length + + "mL2capBuffer= " + mL2capBuffer); + } if (mL2capBuffer == null) { createL2capRxBuffer(); } @@ -511,16 +534,19 @@ public final class BluetoothSocket implements Closeable { if (bytesToRead > mL2capBuffer.remaining()) { bytesToRead = mL2capBuffer.remaining(); } - if(VDBG) Log.v(TAG, "get(): offset: " + offset - + " bytesToRead: " + bytesToRead); + if (VDBG) { + Log.v(TAG, "get(): offset: " + offset + + " bytesToRead: " + bytesToRead); + } mL2capBuffer.get(b, offset, bytesToRead); ret = bytesToRead; - }else { + } else { if (VDBG) Log.v(TAG, "default: read(): offset: " + offset + " length:" + length); ret = mSocketIS.read(b, offset, length); } - if (ret < 0) + if (ret < 0) { throw new IOException("bt socket closed, read return: " + ret); + } if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); return ret; } @@ -532,48 +558,49 @@ public final class BluetoothSocket implements Closeable { // splitting the write into multiple smaller writes. // Rfcomm uses dynamic allocation, and should not have any bindings // to the actual message length. - if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); - if (mType == TYPE_L2CAP) { - if(length <= mMaxTxPacketSize) { - mSocketOS.write(b, offset, length); - } else { - if(DBG) Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n" + if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); + if (mType == TYPE_L2CAP) { + if (length <= mMaxTxPacketSize) { + mSocketOS.write(b, offset, length); + } else { + if (DBG) { + Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n" + "Packet will be divided into SDU packets of size " + mMaxTxPacketSize); - int tmpOffset = offset; - int bytesToWrite = length; - while (bytesToWrite > 0) { - int tmpLength = (bytesToWrite > mMaxTxPacketSize) - ? mMaxTxPacketSize - : bytesToWrite; - mSocketOS.write(b, tmpOffset, tmpLength); - tmpOffset += tmpLength; - bytesToWrite -= tmpLength; - } } - } else { - mSocketOS.write(b, offset, length); + int tmpOffset = offset; + int bytesToWrite = length; + while (bytesToWrite > 0) { + int tmpLength = (bytesToWrite > mMaxTxPacketSize) + ? mMaxTxPacketSize + : bytesToWrite; + mSocketOS.write(b, tmpOffset, tmpLength); + tmpOffset += tmpLength; + bytesToWrite -= tmpLength; + } } - // There is no good way to confirm since the entire process is asynchronous anyway - if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); - return length; + } else { + mSocketOS.write(b, offset, length); + } + // There is no good way to confirm since the entire process is asynchronous anyway + if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); + return length; } @Override public void close() throws IOException { Log.d(TAG, "close() this: " + this + ", channel: " + mPort + - ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + - "mSocket: " + mSocket + ", mSocketState: " + mSocketState); - if(mSocketState == SocketState.CLOSED) + ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + + "mSocket: " + mSocket + ", mSocketState: " + mSocketState); + if (mSocketState == SocketState.CLOSED) { return; - else - { - synchronized(this) - { - if(mSocketState == SocketState.CLOSED) + } else { + synchronized (this) { + if (mSocketState == SocketState.CLOSED) { return; - mSocketState = SocketState.CLOSED; - if(mSocket != null) { + } + mSocketState = SocketState.CLOSED; + if (mSocket != null) { if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket); mSocket.shutdownInput(); mSocket.shutdownOutput(); @@ -584,7 +611,7 @@ public final class BluetoothSocket implements Closeable { mPfd.close(); mPfd = null; } - } + } } } @@ -599,9 +626,10 @@ public final class BluetoothSocket implements Closeable { * Get the maximum supported Transmit packet size for the underlying transport. * Use this to optimize the writes done to the output socket, to avoid sending * half full packets. + * * @return the maximum supported Transmit packet size for the underlying transport. */ - public int getMaxTransmitPacketSize(){ + public int getMaxTransmitPacketSize() { return mMaxTxPacketSize; } @@ -610,14 +638,16 @@ public final class BluetoothSocket implements Closeable { * Use this to optimize the reads done on the input stream, as any call to read * will return a maximum of this amount of bytes - or for some transports a * multiple of this value. + * * @return the maximum supported Receive packet size for the underlying transport. */ - public int getMaxReceivePacketSize(){ + public int getMaxReceivePacketSize() { return mMaxRxPacketSize; } /** * Get the type of the underlying connection. + * * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP} */ public int getConnectionType() { @@ -627,67 +657,79 @@ public final class BluetoothSocket implements Closeable { /** * Change if a SDP entry should be automatically created. * Must be called before calling .bind, for the call to have any effect. - * @param mExcludeSdp

  • TRUE - do not auto generate SDP record. - *
  • FALSE - default - auto generate SPP SDP record. + * + * @param mExcludeSdp
  • TRUE - do not auto generate SDP record.
  • FALSE - default - auto + * generate SPP SDP record. * @hide */ public void setExcludeSdp(boolean excludeSdp) { this.mExcludeSdp = excludeSdp; } - private String convertAddr(final byte[] addr) { + private String convertAddr(final byte[] addr) { return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", - addr[0] , addr[1], addr[2], addr[3] , addr[4], addr[5]); + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); } + private String waitSocketSignal(InputStream is) throws IOException { - byte [] sig = new byte[SOCK_SIGNAL_SIZE]; + byte[] sig = new byte[SOCK_SIGNAL_SIZE]; int ret = readAll(is, sig); - if (VDBG) Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + - " bytes signal ret: " + ret); + if (VDBG) { + Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + + " bytes signal ret: " + ret); + } ByteBuffer bb = ByteBuffer.wrap(sig); /* the struct in native is decorated with __attribute__((packed)), hence this is possible */ bb.order(ByteOrder.nativeOrder()); int size = bb.getShort(); - if(size != SOCK_SIGNAL_SIZE) + if (size != SOCK_SIGNAL_SIZE) { throw new IOException("Connection failure, wrong signal size: " + size); - byte [] addr = new byte[6]; + } + byte[] addr = new byte[6]; bb.get(addr); int channel = bb.getInt(); int status = bb.getInt(); mMaxTxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value mMaxRxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value String RemoteAddr = convertAddr(addr); - if (VDBG) Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: " - + RemoteAddr + ", channel: " + channel + ", status: " + status - + " MaxRxPktSize: " + mMaxRxPacketSize + " MaxTxPktSize: " + mMaxTxPacketSize); - if(status != 0) + if (VDBG) { + Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: " + + RemoteAddr + ", channel: " + channel + ", status: " + status + + " MaxRxPktSize: " + mMaxRxPacketSize + " MaxTxPktSize: " + mMaxTxPacketSize); + } + if (status != 0) { throw new IOException("Connection failure, status: " + status); + } return RemoteAddr; } - private void createL2capRxBuffer(){ - if(mType == TYPE_L2CAP) { + private void createL2capRxBuffer() { + if (mType == TYPE_L2CAP) { // Allocate the buffer to use for reads. - if(VDBG) Log.v(TAG, " Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize); + if (VDBG) Log.v(TAG, " Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize); mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]); - if(VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining()); + if (VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining()); mL2capBuffer.limit(0); // Ensure we do a real read at the first read-request - if(VDBG) Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + - mL2capBuffer.remaining()); + if (VDBG) { + Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + + mL2capBuffer.remaining()); + } } } private int readAll(InputStream is, byte[] b) throws IOException { int left = b.length; - while(left > 0) { + while (left > 0) { int ret = is.read(b, b.length - left, left); - if(ret <= 0) - throw new IOException("read failed, socket might closed or timeout, read ret: " - + ret); + if (ret <= 0) { + throw new IOException("read failed, socket might closed or timeout, read ret: " + + ret); + } left -= ret; - if(left != 0) + if (left != 0) { Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) + - ", expect size: " + b.length); + ", expect size: " + b.length); + } } return b.length; } @@ -704,7 +746,7 @@ public final class BluetoothSocket implements Closeable { private int fillL2capRxBuffer() throws IOException { mL2capBuffer.rewind(); int ret = mSocketIS.read(mL2capBuffer.array()); - if(ret == -1) { + if (ret == -1) { // reached end of stream - return -1 mL2capBuffer.limit(0); return -1; -- cgit v1.2.3 From 9e045d26d0128826b40520f523307d8d16473779 Mon Sep 17 00:00:00 2001 From: Jack He Date: Tue, 22 Aug 2017 21:21:23 -0700 Subject: Fix checkstyle errors (2/2) * Manual style corrections with IDE assistance * Variable name refactors are done through IDE * Corrected general style errors such as: - "final private var" -> "private final var" - "&&", "+", "||" should not be at the end of line - Non-static private variable should be like "mVar" - Private static variable should be like "sVar" - Code file should always end with newline - Inherited methods should be annotated with @Override and no @hide tags - Public methods should always have a JavaDoc entry - "int[] array" is preferred over "int array[]" - private methods should be accessed without "this." when there is no name collisions. - "boolean ? true : false" -> boolean - "boolean ? false : true" -> !boolean - "boolean == true" OR "boolean != false" -> boolean - "boolean != true" OR "boolean == false" -> !boolean Bug: 63596319 Test: make checkbuild, no functional changes Change-Id: Iabdc2be912a32dd63a53213d175cf1bfef268ccd --- .../java/android/bluetooth/BluetoothSocket.java | 33 ++++++++++------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index a90dd82b96..4035ee1beb 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -126,9 +126,9 @@ public final class BluetoothSocket implements Closeable { private int mPort; /* RFCOMM channel or L2CAP psm */ private int mFd; private String mServiceName; - private static int PROXY_CONNECTION_TIMEOUT = 5000; + private static final int PROXY_CONNECTION_TIMEOUT = 5000; - private static int SOCK_SIGNAL_SIZE = 20; + private static final int SOCK_SIGNAL_SIZE = 20; private ByteBuffer mL2capBuffer = null; private int mMaxTxPacketSize = 0; // The l2cap maximum packet size supported by the peer. @@ -235,7 +235,7 @@ public final class BluetoothSocket implements Closeable { mMin16DigitPin = s.mMin16DigitPin; } - private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException { + private BluetoothSocket acceptSocket(String remoteAddr) throws IOException { BluetoothSocket as = new BluetoothSocket(this); as.mSocketState = SocketState.CONNECTED; FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors(); @@ -250,8 +250,8 @@ public final class BluetoothSocket implements Closeable { as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]); as.mSocketIS = as.mSocket.getInputStream(); as.mSocketOS = as.mSocket.getOutputStream(); - as.mAddress = RemoteAddr; - as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(RemoteAddr); + as.mAddress = remoteAddr; + as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr); return as; } @@ -428,8 +428,7 @@ public final class BluetoothSocket implements Closeable { try { synchronized (this) { if (DBG) { - Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + - mPfd); + Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd); } if (mSocketState != SocketState.INIT) return EBADFD; if (mPfd == null) return -1; @@ -589,9 +588,9 @@ public final class BluetoothSocket implements Closeable { @Override public void close() throws IOException { - Log.d(TAG, "close() this: " + this + ", channel: " + mPort + - ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + - "mSocket: " + mSocket + ", mSocketState: " + mSocketState); + Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS + + ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket + ", mSocketState: " + + mSocketState); if (mSocketState == SocketState.CLOSED) { return; } else { @@ -658,12 +657,12 @@ public final class BluetoothSocket implements Closeable { * Change if a SDP entry should be automatically created. * Must be called before calling .bind, for the call to have any effect. * - * @param mExcludeSdp
  • TRUE - do not auto generate SDP record.
  • FALSE - default - auto + * @param excludeSdp
  • TRUE - do not auto generate SDP record.
  • FALSE - default - auto * generate SPP SDP record. * @hide */ public void setExcludeSdp(boolean excludeSdp) { - this.mExcludeSdp = excludeSdp; + mExcludeSdp = excludeSdp; } private String convertAddr(final byte[] addr) { @@ -675,8 +674,7 @@ public final class BluetoothSocket implements Closeable { byte[] sig = new byte[SOCK_SIGNAL_SIZE]; int ret = readAll(is, sig); if (VDBG) { - Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + - " bytes signal ret: " + ret); + Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + " bytes signal ret: " + ret); } ByteBuffer bb = ByteBuffer.wrap(sig); /* the struct in native is decorated with __attribute__((packed)), hence this is possible */ @@ -711,8 +709,7 @@ public final class BluetoothSocket implements Closeable { if (VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining()); mL2capBuffer.limit(0); // Ensure we do a real read at the first read-request if (VDBG) { - Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + - mL2capBuffer.remaining()); + Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + mL2capBuffer.remaining()); } } } @@ -727,8 +724,8 @@ public final class BluetoothSocket implements Closeable { } left -= ret; if (left != 0) { - Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) + - ", expect size: " + b.length); + Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) + + ", expect size: " + b.length); } } return b.length; -- cgit v1.2.3 From f831af96f0d4dfa8041e0d74a4b88911aac7eddf Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Mon, 6 Nov 2017 12:16:25 -0800 Subject: Move createSocketChannel into IBluetoothSocketManager (3/3) Bug: 68359837 Test: none Change-Id: I52b03ff3d637bf661c70279b7ca18b105157f7a2 --- framework/java/android/bluetooth/BluetoothSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 4035ee1beb..23956e14d9 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -417,7 +417,7 @@ public final class BluetoothSocket implements Closeable { return -1; } try { - mPfd = bluetoothProxy.createSocketChannel(mType, mServiceName, + mPfd = bluetoothProxy.getSocketManager().createSocketChannel(mType, mServiceName, mUuid, mPort, getSecurityFlags()); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); -- cgit v1.2.3 From 3f78e6ced9cb29f364b55870f8a31af8ae6d5c93 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Mon, 6 Nov 2017 12:17:30 -0800 Subject: Move connectSocket into IBluetoothSocketManager (3/3) Bug: 68359837 Test: none Merged-In: I1161a5fe74b034fba0112fd3a78bdf1fbace6e12 Change-Id: I1161a5fe74b034fba0112fd3a78bdf1fbace6e12 --- framework/java/android/bluetooth/BluetoothSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 23956e14d9..0569913435 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -375,7 +375,7 @@ public final class BluetoothSocket implements Closeable { IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); if (bluetoothProxy == null) throw new IOException("Bluetooth is off"); - mPfd = bluetoothProxy.connectSocket(mDevice, mType, + mPfd = bluetoothProxy.getSocketManager().connectSocket(mDevice, mType, mUuid, mPort, getSecurityFlags()); synchronized (this) { if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd); -- cgit v1.2.3 From d67d5e4f1e8c1afd98f11b11ca8ca26792da9d6b Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Wed, 22 Nov 2017 16:04:40 -0800 Subject: Added APIs for Connection-oriented channels Experimental and hidden APIs are defined for the Connection-oriented Channel (CoC) features. The APIs using PSM are implemented. Test: Can compile Bug: 70683224 Change-Id: Icdb5fa190b0e21881a60437fa48cd575371ee1e4 --- framework/java/android/bluetooth/BluetoothSocket.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 0569913435..09f96840f9 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -99,6 +99,16 @@ public final class BluetoothSocket implements Closeable { /** L2CAP socket */ public static final int TYPE_L2CAP = 3; + /** L2CAP socket on BR/EDR transport + * @hide + */ + public static final int TYPE_L2CAP_BREDR = TYPE_L2CAP; + + /** L2CAP socket on LE transport + * @hide + */ + public static final int TYPE_L2CAP_LE = 4; + /*package*/ static final int EBADFD = 77; /*package*/ static final int EADDRINUSE = 98; @@ -417,6 +427,7 @@ public final class BluetoothSocket implements Closeable { return -1; } try { + if (DBG) Log.d(TAG, "bindListen(): mPort=" + mPort + ", mType=" + mType); mPfd = bluetoothProxy.getSocketManager().createSocketChannel(mType, mServiceName, mUuid, mPort, getSecurityFlags()); } catch (RemoteException e) { @@ -451,7 +462,7 @@ public final class BluetoothSocket implements Closeable { mSocketState = SocketState.LISTENING; } } - if (DBG) Log.d(TAG, "channel: " + channel); + if (DBG) Log.d(TAG, "bindListen(): channel=" + channel + ", mPort=" + mPort); if (mPort <= -1) { mPort = channel; } // else ASSERT(mPort == channel) @@ -515,7 +526,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ int read(byte[] b, int offset, int length) throws IOException { int ret = 0; if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); - if (mType == TYPE_L2CAP) { + if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) { int bytesToRead = length; if (VDBG) { Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length @@ -558,7 +569,7 @@ public final class BluetoothSocket implements Closeable { // Rfcomm uses dynamic allocation, and should not have any bindings // to the actual message length. if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); - if (mType == TYPE_L2CAP) { + if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) { if (length <= mMaxTxPacketSize) { mSocketOS.write(b, offset, length); } else { @@ -702,7 +713,7 @@ public final class BluetoothSocket implements Closeable { } private void createL2capRxBuffer() { - if (mType == TYPE_L2CAP) { + if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) { // Allocate the buffer to use for reads. if (VDBG) Log.v(TAG, " Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize); mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]); -- cgit v1.2.3 From cf3cfd339a2635b0ccd94ad9a3eaa7229a8f3d54 Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Tue, 16 Jan 2018 10:39:32 -0800 Subject: Add function to change LE Tx Data Length As part of new SL4A tests for LE CoC to measure data throughput, this commit adds a function to set the LE Tx Data Length parameter to its maximum. Test: Ran the new ACTS Tests for LE CoC (BleCocTest and BleCoc2ConnTest) Bug: 70683224 Change-Id: Iea93f6cb9f4f7cc484f121afa158d7dae18d1ef1 --- .../java/android/bluetooth/BluetoothSocket.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 09f96840f9..09a5b593e5 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -676,6 +676,35 @@ public final class BluetoothSocket implements Closeable { mExcludeSdp = excludeSdp; } + /** + * Set the LE Transmit Data Length to be the maximum that the BT Controller is capable of. This + * parameter is used by the BT Controller to set the maximum transmission packet size on this + * connection. This function is currently used for testing only. + * @hide + */ + public void requestMaximumTxDataLength() throws IOException { + if (mDevice == null) { + throw new IOException("requestMaximumTxDataLength is called on null device"); + } + + try { + if (mSocketState == SocketState.CLOSED) { + throw new IOException("socket closed"); + } + IBluetooth bluetoothProxy = + BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + if (bluetoothProxy == null) { + throw new IOException("Bluetooth is off"); + } + + if (DBG) Log.d(TAG, "requestMaximumTxDataLength"); + bluetoothProxy.getSocketManager().requestMaximumTxDataLength(mDevice); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + throw new IOException("unable to send RPC: " + e.getMessage()); + } + } + private String convertAddr(final byte[] addr) { return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); -- cgit v1.2.3 From 7d543894e0497651fc160728d659543483500f87 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Wed, 1 Aug 2018 15:07:20 +0100 Subject: Add @UnsupportedAppUsage annotations For packages: android.bluetooth.le android.bluetooth This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Change-Id: Ifcf24c0617acd7facc0e03f30a95c3a6b09b205c Merged-In: I88a1311e27c5f9a5f9d1035db76034f86f650efc --- framework/java/android/bluetooth/BluetoothSocket.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 09a5b593e5..780f896139 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.net.LocalSocket; import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; @@ -110,6 +111,7 @@ public final class BluetoothSocket implements Closeable { public static final int TYPE_L2CAP_LE = 4; /*package*/ static final int EBADFD = 77; + @UnsupportedAppUsage /*package*/ static final int EADDRINUSE = 98; /*package*/ static final int SEC_FLAG_ENCRYPT = 1; @@ -129,10 +131,13 @@ public final class BluetoothSocket implements Closeable { private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */ private boolean mAuthMitm = false; /* when true Man-in-the-middle protection will be enabled*/ private boolean mMin16DigitPin = false; /* Minimum 16 digit pin for sec mode 2 connections */ + @UnsupportedAppUsage private ParcelFileDescriptor mPfd; + @UnsupportedAppUsage private LocalSocket mSocket; private InputStream mSocketIS; private OutputStream mSocketOS; + @UnsupportedAppUsage private int mPort; /* RFCOMM channel or L2CAP psm */ private int mFd; private String mServiceName; @@ -517,6 +522,7 @@ public final class BluetoothSocket implements Closeable { * * @throws IOException if an i/o error occurs. */ + @UnsupportedAppUsage /*package*/ void flush() throws IOException { if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); if (VDBG) Log.d(TAG, "flush: " + mSocketOS); -- cgit v1.2.3 From 412cbec0c57647b955747e9b55bce071870b9a1e Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Fri, 29 Jun 2018 14:05:04 -0700 Subject: Unhide the LE CoC APIs Expose the LE Connection-oriented Channels APIs for applications to use. Test: Run the SL4A ACTS test: BleCocTest Bug: 70683224 Change-Id: I68128bc7154966ec065091c973351f8892da9b4d --- framework/java/android/bluetooth/BluetoothSocket.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 780f896139..3a1e2f58c9 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -667,6 +667,10 @@ public final class BluetoothSocket implements Closeable { * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP} */ public int getConnectionType() { + if (mType == TYPE_L2CAP_LE) { + // Treat the LE CoC to be the same type as L2CAP. + return TYPE_L2CAP; + } return mType; } -- cgit v1.2.3 From 147146fb21165bdf7812fa9745ca797b7d12b437 Mon Sep 17 00:00:00 2001 From: Andrei Onea Date: Mon, 17 Jun 2019 11:26:14 +0100 Subject: Document public alternatives to greylisted APIs Add known public alternatives or recommendations for greylisted APIs in Bluetooth. Bug: 135171386 Test: m Change-Id: I86e708be37eb7d1b0fafa2d64283b7f81bc02e51 --- framework/java/android/bluetooth/BluetoothSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 3a1e2f58c9..a6e3153d6a 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -131,7 +131,7 @@ public final class BluetoothSocket implements Closeable { private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */ private boolean mAuthMitm = false; /* when true Man-in-the-middle protection will be enabled*/ private boolean mMin16DigitPin = false; /* Minimum 16 digit pin for sec mode 2 connections */ - @UnsupportedAppUsage + @UnsupportedAppUsage(publicAlternatives = "Use {@link BluetoothSocket} public API instead.") private ParcelFileDescriptor mPfd; @UnsupportedAppUsage private LocalSocket mSocket; -- cgit v1.2.3 From 0388ad1f72c70ca96cabc8b1a4a107877752b187 Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Wed, 21 Aug 2019 17:22:54 -0700 Subject: Remove a misleading "flush" function. This patch removes LocalSocketImpl.flush(). In practice this function was simply a wrapper around `Thread.sleep(10)`. All direct calls to this function have been removed. The `flush()` function is still called on several objects that wrap a SocketOutputStream. This will make booting a device 20ms faster than it currently is. Bug: 139192244 Test: Build -> flash -> boot -> launch app Change-Id: I0a96f4bc72461670370f61e847349f32af5ac774 --- framework/java/android/bluetooth/BluetoothSocket.java | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index a6e3153d6a..760166bfcc 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -515,20 +515,6 @@ public final class BluetoothSocket implements Closeable { return mSocketIS.available(); } - /** - * Wait until the data in sending queue is emptied. A polling version - * for flush implementation. Used to ensure the writing data afterwards will - * be packed in new RFCOMM frame. - * - * @throws IOException if an i/o error occurs. - */ - @UnsupportedAppUsage - /*package*/ void flush() throws IOException { - if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); - if (VDBG) Log.d(TAG, "flush: " + mSocketOS); - mSocketOS.flush(); - } - /*package*/ int read(byte[] b, int offset, int length) throws IOException { int ret = 0; if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); -- cgit v1.2.3 From 3d30e625e338d452c2a9e91dc2ad477e8500e5eb Mon Sep 17 00:00:00 2001 From: Ian Kasprzak Date: Sat, 31 Aug 2019 21:28:50 +0000 Subject: Revert "Remove a misleading "flush" function." This reverts commit 0388ad1f72c70ca96cabc8b1a4a107877752b187. Reason for revert: Driodcop: aosp-master test-mapping showing multiple failures (b/140336855). Change-Id: If44e273dd111802db8b44db1e5a67a4628c72e3c --- framework/java/android/bluetooth/BluetoothSocket.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 760166bfcc..a6e3153d6a 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -515,6 +515,20 @@ public final class BluetoothSocket implements Closeable { return mSocketIS.available(); } + /** + * Wait until the data in sending queue is emptied. A polling version + * for flush implementation. Used to ensure the writing data afterwards will + * be packed in new RFCOMM frame. + * + * @throws IOException if an i/o error occurs. + */ + @UnsupportedAppUsage + /*package*/ void flush() throws IOException { + if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); + if (VDBG) Log.d(TAG, "flush: " + mSocketOS); + mSocketOS.flush(); + } + /*package*/ int read(byte[] b, int offset, int length) throws IOException { int ret = 0; if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); -- cgit v1.2.3 From 4fd500310f8738adfb2d7dd6e32b576ab7b00ab8 Mon Sep 17 00:00:00 2001 From: Christian Wailes Date: Wed, 4 Sep 2019 23:35:54 +0000 Subject: Revert "Revert "Remove a misleading "flush" function."" This reverts commit 3d30e625e338d452c2a9e91dc2ad477e8500e5eb. Reason for revert: Fixed the test broken by the original commit Bug: 139192244 Bug: 140336855 Test: m -> flash -> boot Test: atest CtsJvmtiAttachingHostTestCases Change-Id: I4c67ad8709652c4710ef24564e0240f74f817f8c --- framework/java/android/bluetooth/BluetoothSocket.java | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index a6e3153d6a..760166bfcc 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -515,20 +515,6 @@ public final class BluetoothSocket implements Closeable { return mSocketIS.available(); } - /** - * Wait until the data in sending queue is emptied. A polling version - * for flush implementation. Used to ensure the writing data afterwards will - * be packed in new RFCOMM frame. - * - * @throws IOException if an i/o error occurs. - */ - @UnsupportedAppUsage - /*package*/ void flush() throws IOException { - if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); - if (VDBG) Log.d(TAG, "flush: " + mSocketOS); - mSocketOS.flush(); - } - /*package*/ int read(byte[] b, int offset, int length) throws IOException { int ret = 0; if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); -- cgit v1.2.3 From d8fe38cc98bb4f49cd0c4ab9d7855f98ee1209f3 Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Tue, 10 Dec 2019 17:47:52 +0000 Subject: Use new UnsupportedAppUsage annotation. Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library. Bug: 145132366 Test: m && diff unsupportedappusage_index.csv Change-Id: I6ab53570aca580fbee1fcc927871caa09780f58f Merged-In: I6ab53570aca580fbee1fcc927871caa09780f58f --- framework/java/android/bluetooth/BluetoothSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 760166bfcc..f774369655 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -16,7 +16,7 @@ package android.bluetooth; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.net.LocalSocket; import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; -- cgit v1.2.3 From c5386afbc18b5164c381b1d8e099327953205436 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 11 Sep 2020 14:57:21 -0600 Subject: Update language to comply with Android's inclusive language guidance See https://source.android.com/setup/contribute/respectful-code for reference Test: none Bug: 168334533 Exempt-From-Owner-Approval: docs updates Change-Id: I245b8d9cac722da76ea67983738a3cbb9deb68df --- framework/java/android/bluetooth/BluetoothSocket.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index f774369655..d41a6d064d 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -128,9 +128,12 @@ public final class BluetoothSocket implements Closeable { private final BluetoothInputStream mInputStream; private final BluetoothOutputStream mOutputStream; private final ParcelUuid mUuid; - private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */ - private boolean mAuthMitm = false; /* when true Man-in-the-middle protection will be enabled*/ - private boolean mMin16DigitPin = false; /* Minimum 16 digit pin for sec mode 2 connections */ + /** when true no SPP SDP record will be created */ + private boolean mExcludeSdp = false; + /** when true Person-in-the-middle protection will be enabled */ + private boolean mAuthMitm = false; + /** Minimum 16 digit pin for sec mode 2 connections */ + private boolean mMin16DigitPin = false; @UnsupportedAppUsage(publicAlternatives = "Use {@link BluetoothSocket} public API instead.") private ParcelFileDescriptor mPfd; @UnsupportedAppUsage @@ -190,7 +193,7 @@ public final class BluetoothSocket implements Closeable { * @param device remote device that this socket can connect to * @param port remote port * @param uuid SDP uuid - * @param mitm enforce man-in-the-middle protection. + * @param mitm enforce person-in-the-middle protection. * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection * @throws IOException On error, for example Bluetooth not available, or insufficient * privileges -- cgit v1.2.3 From bc9a809f18a3b0ec23cbc39802fb4928c2074ea3 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Tue, 27 Oct 2020 11:47:29 +0000 Subject: Add maxTargetSdk restriction to unused APIs. These are APIs that have @UnsupportedAppUsage but for which we don't have any evidence of them currently being used, so should be safe to remove from the unsupported list. Bug: 170729553 Test: Treehugger Change-Id: I4c8fd0006f950de9955242e93968fb0996ceb372 --- framework/java/android/bluetooth/BluetoothSocket.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d41a6d064d..65381dbb23 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -18,6 +18,7 @@ package android.bluetooth; import android.compat.annotation.UnsupportedAppUsage; import android.net.LocalSocket; +import android.os.Build; import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; import android.os.RemoteException; @@ -111,7 +112,7 @@ public final class BluetoothSocket implements Closeable { public static final int TYPE_L2CAP_LE = 4; /*package*/ static final int EBADFD = 77; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) /*package*/ static final int EADDRINUSE = 98; /*package*/ static final int SEC_FLAG_ENCRYPT = 1; -- cgit v1.2.3 From bddbb77484a3694357df750c5e7df9527f409c8a Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Wed, 28 Oct 2020 19:38:11 +0000 Subject: Revert "Add maxTargetSdk restriction to unused APIs." This reverts commit bc9a809f18a3b0ec23cbc39802fb4928c2074ea3. Reason for revert: Droidcop-triggered revert due to breakage https://android-build.googleplex.com/builds/quarterdeck?testMethod=testAppZygotePreload&testClass=android.app.cts.ServiceTest&atpConfigName=suite%2Ftest-mapping-presubmit-retry_cloud-tf&testModule=CtsAppTestCases&fkbb=6936597&lkbb=6936969&lkgb=6936551&testResults=true&branch=git_master&target=cf_x86_phone-userdebug>, bug b/171886397 Bug: 171886397 Change-Id: Ibe0f0430a3451477c1ee8ef56a596e91ea1e7672 --- framework/java/android/bluetooth/BluetoothSocket.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 65381dbb23..d41a6d064d 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -18,7 +18,6 @@ package android.bluetooth; import android.compat.annotation.UnsupportedAppUsage; import android.net.LocalSocket; -import android.os.Build; import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; import android.os.RemoteException; @@ -112,7 +111,7 @@ public final class BluetoothSocket implements Closeable { public static final int TYPE_L2CAP_LE = 4; /*package*/ static final int EBADFD = 77; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage /*package*/ static final int EADDRINUSE = 98; /*package*/ static final int SEC_FLAG_ENCRYPT = 1; -- cgit v1.2.3 From cba870b777fc6d2a03a27758cf1db1c38556efe8 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Tue, 27 Oct 2020 11:47:29 +0000 Subject: Add maxTargetSdk restriction to unused APIs. These are APIs that have @UnsupportedAppUsage but for which we don't have any evidence of them currently being used, so should be safe to remove from the unsupported list. This is a resubmit of ag/12929664 with some APIs excluded that caused test failures; see bugs 171886397, 171888296, 171864568. APIs excluded: Landroid/bluetooth/le/ScanRecord;->parseFromBytes([B)Landroid/bluetooth/le/ScanRecord; Landroid/os/Process;->myPpid()I Landroid/os/SharedMemory;->getFd()I Landroid/hardware/input/InputManager;->INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH:I Bug: 170729553 Test: Treehugger Change-Id: I8285daa8530260251ecad6f3f38f98e263629ca7 --- framework/java/android/bluetooth/BluetoothSocket.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d41a6d064d..65381dbb23 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -18,6 +18,7 @@ package android.bluetooth; import android.compat.annotation.UnsupportedAppUsage; import android.net.LocalSocket; +import android.os.Build; import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; import android.os.RemoteException; @@ -111,7 +112,7 @@ public final class BluetoothSocket implements Closeable { public static final int TYPE_L2CAP_LE = 4; /*package*/ static final int EBADFD = 77; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) /*package*/ static final int EADDRINUSE = 98; /*package*/ static final int SEC_FLAG_ENCRYPT = 1; -- cgit v1.2.3 From 8f80e4a05b3f1b227f40de5ec0e9a6297154ffc0 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 2 Apr 2021 08:06:09 -0600 Subject: Update Bluetooth API annotations. Recent work has introduced a new "Nearby devices" runtime permission which protects all existing Bluetooth APIs; we've done this by defining a to convert the old BLUETOOTH and BLUETOOTH_ADMIN permissions into one of three new permissions: * BLUETOOTH_ADVERTISE: Required to be able to advertise to nearby Bluetooth devices. * BLUETOOTH_CONNECT: Allows applications to connect to paired bluetooth devices. * BLUETOOTH_SCAN: Required to be able to discover and pair nearby Bluetooth devices. At its core, this change begins updating the Bluetooth APIs to have correct @RequiresPermission indicating which permission is actually enforced internally. To ensure alignment across Binder, the newly added "RequiresPermissionChecker" Error Prone checker was used to discover any inconsistencies, ensuring correctness from server-side enforcement up through to the public APIs. In addition, since developers will continue building apps for both modern and legacy platforms, this change introduces new auto-doc annotations which will emit helpful consistent documentation describing the behavior of older devices that are still using the old permission model. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: I02aa127e8e07f239561f4f2a3bbdfc6fccb82f7f --- framework/java/android/bluetooth/BluetoothSocket.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 65381dbb23..ef88147a40 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -16,6 +16,8 @@ package android.bluetooth; +import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.compat.annotation.UnsupportedAppUsage; import android.net.LocalSocket; import android.os.Build; @@ -70,9 +72,6 @@ import java.util.UUID; * safe. In particular, {@link #close} will always immediately abort ongoing * operations and close the socket. * - *

    Note: - * Requires the {@link android.Manifest.permission#BLUETOOTH} permission. - * *

    *

    Developer Guides

    *

    For more information about using Bluetooth, read the @@ -199,6 +198,7 @@ public final class BluetoothSocket implements Closeable { * @throws IOException On error, for example Bluetooth not available, or insufficient * privileges */ + @SuppressLint("AndroidFrameworkRequiresPermission") /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin) throws IOException { @@ -386,6 +386,7 @@ public final class BluetoothSocket implements Closeable { * * @throws IOException on error, for example connection failure */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void connect() throws IOException { if (mDevice == null) throw new IOException("Connect is called on null device"); @@ -427,6 +428,7 @@ public final class BluetoothSocket implements Closeable { * Currently returns unix errno instead of throwing IOException, * so that BluetoothAdapter can check the error code for EADDRINUSE */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) /*package*/ int bindListen() { int ret; if (mSocketState == SocketState.CLOSED) return EBADFD; @@ -682,6 +684,7 @@ public final class BluetoothSocket implements Closeable { * connection. This function is currently used for testing only. * @hide */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void requestMaximumTxDataLength() throws IOException { if (mDevice == null) { throw new IOException("requestMaximumTxDataLength is called on null device"); -- cgit v1.2.3 From 5ba8bfca7e9adf5c6d8ee8180aebad6f04037d6c Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 16 Apr 2021 09:53:23 -0600 Subject: More Bluetooth API annotation updates. This change adds a "BluetoothPermissionChecker" that ensures that all Bluetooth permission annotations are consistent. In addition, it verifies that all Bluetooth public APIs have been audited to be permission protected where relevant. We've currently standardized on saying that APIs that return device or Bluetooth state information (without sharing details about any particular remote Bluetooth device) do not need to be permission protected. This change is only annotations and has no behavior changes. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: Ie80b15b058359bf1e9a6ee881b89cb3e5b584ca1 --- framework/java/android/bluetooth/BluetoothSocket.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index ef88147a40..bb409d5360 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -16,8 +16,10 @@ package android.bluetooth; +import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; +import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; import android.net.LocalSocket; import android.os.Build; @@ -198,7 +200,6 @@ public final class BluetoothSocket implements Closeable { * @throws IOException On error, for example Bluetooth not available, or insufficient * privileges */ - @SuppressLint("AndroidFrameworkRequiresPermission") /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin) throws IOException { @@ -326,6 +327,7 @@ public final class BluetoothSocket implements Closeable { * * @return remote device */ + @RequiresNoPermission public BluetoothDevice getRemoteDevice() { return mDevice; } @@ -338,6 +340,7 @@ public final class BluetoothSocket implements Closeable { * * @return InputStream */ + @RequiresNoPermission public InputStream getInputStream() throws IOException { return mInputStream; } @@ -350,6 +353,7 @@ public final class BluetoothSocket implements Closeable { * * @return OutputStream */ + @RequiresNoPermission public OutputStream getOutputStream() throws IOException { return mOutputStream; } @@ -360,6 +364,7 @@ public final class BluetoothSocket implements Closeable { * * @return true if connected false if not connected */ + @RequiresNoPermission public boolean isConnected() { return mSocketState == SocketState.CONNECTED; } @@ -386,6 +391,7 @@ public final class BluetoothSocket implements Closeable { * * @throws IOException on error, for example connection failure */ + @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void connect() throws IOException { if (mDevice == null) throw new IOException("Connect is called on null device"); @@ -637,6 +643,7 @@ public final class BluetoothSocket implements Closeable { * * @return the maximum supported Transmit packet size for the underlying transport. */ + @RequiresNoPermission public int getMaxTransmitPacketSize() { return mMaxTxPacketSize; } @@ -649,6 +656,7 @@ public final class BluetoothSocket implements Closeable { * * @return the maximum supported Receive packet size for the underlying transport. */ + @RequiresNoPermission public int getMaxReceivePacketSize() { return mMaxRxPacketSize; } @@ -658,6 +666,7 @@ public final class BluetoothSocket implements Closeable { * * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP} */ + @RequiresNoPermission public int getConnectionType() { if (mType == TYPE_L2CAP_LE) { // Treat the LE CoC to be the same type as L2CAP. @@ -674,6 +683,7 @@ public final class BluetoothSocket implements Closeable { * generate SPP SDP record. * @hide */ + @RequiresNoPermission public void setExcludeSdp(boolean excludeSdp) { mExcludeSdp = excludeSdp; } @@ -684,6 +694,7 @@ public final class BluetoothSocket implements Closeable { * connection. This function is currently used for testing only. * @hide */ + @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void requestMaximumTxDataLength() throws IOException { if (mDevice == null) { -- cgit v1.2.3 From a1157dbeedfecfdb039802cee22a5f5e1abf0cf8 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 10 Aug 2021 16:50:52 -0600 Subject: Register IBluetoothManagerCallback per-process. As part of introducing AttributionSource across the Bluetooth stack earlier this year, each BluetoothAdapter instance is now associated with a specific AttributionSource, and several instances of shared static code were made BluetoothAdapter-specific so they could be augmented with the relevant AttributionSource. However, processes that create many BluetoothAdapter instances can overload the system, since a IBluetoothManagerCallback was registered for each instance. This change mitigates this by only registering a single IBluetoothManagerCallback for the entire process, and it then reuses the existing sProxyServiceStateCallbacks list for dispatching events to all active adapters within the process. Since it's so late in the release, we keep both mService and sService intact to minimize the size of this CL; future work should refactor to a more robust design, such as Supplier. Bug: 195286998, 172022978 Test: atest BluetoothInstrumentationTests Change-Id: I012f3f65e61eaf55e40436486806e56506c928ee (cherry picked from commit f0fa7f9b4aaee876053486d988909df9dc64e990) --- framework/java/android/bluetooth/BluetoothSocket.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index bb409d5360..1655b62bbf 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -399,7 +399,7 @@ public final class BluetoothSocket implements Closeable { try { if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); IBluetooth bluetoothProxy = - BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + BluetoothAdapter.getDefaultAdapter().getBluetoothService(); if (bluetoothProxy == null) throw new IOException("Bluetooth is off"); mPfd = bluetoothProxy.getSocketManager().connectSocket(mDevice, mType, mUuid, mPort, getSecurityFlags()); @@ -438,7 +438,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ int bindListen() { int ret; if (mSocketState == SocketState.CLOSED) return EBADFD; - IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(); if (bluetoothProxy == null) { Log.e(TAG, "bindListen fail, reason: bluetooth is off"); return -1; @@ -706,7 +706,7 @@ public final class BluetoothSocket implements Closeable { throw new IOException("socket closed"); } IBluetooth bluetoothProxy = - BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + BluetoothAdapter.getDefaultAdapter().getBluetoothService(); if (bluetoothProxy == null) { throw new IOException("Bluetooth is off"); } -- cgit v1.2.3 From 88eade5300ce39db2c157bb32dac30df961a9d1f Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 19 Nov 2021 16:48:45 +0100 Subject: BT MAINLINE ParcelFileDescriptor to dup method In order to have Bluetooth a mainline module, we must remove all call to externa hidden API. Tag: #refactor Bug: 200200870 Test: Build Change-Id: I291d670b1dfc3760bedd5f6666ea04883568df69 --- framework/java/android/bluetooth/BluetoothSocket.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothSocket.java') diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 1655b62bbf..db5b75148e 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -18,7 +18,6 @@ package android.bluetooth; import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; -import android.annotation.SuppressLint; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; import android.net.LocalSocket; @@ -266,7 +265,7 @@ public final class BluetoothSocket implements Closeable { throw new IOException("bt socket acept failed"); } - as.mPfd = new ParcelFileDescriptor(fds[0]); + as.mPfd = ParcelFileDescriptor.dup(fds[0]); as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]); as.mSocketIS = as.mSocket.getInputStream(); as.mSocketOS = as.mSocket.getOutputStream(); -- cgit v1.2.3