Skip to content
Snippets Groups Projects
Commit cd5d922b authored by akwizgran's avatar akwizgran
Browse files

Cleaned up Android Bluetooth reflection code and added logging.

parent a02ca4b3
No related branches found
No related tags found
No related merge requests found
package net.sf.briar.plugins.droidtooth; package net.sf.briar.plugins.droidtooth;
import static java.util.logging.Level.INFO;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Logger;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
...@@ -21,16 +24,22 @@ import android.os.ParcelUuid; ...@@ -21,16 +24,22 @@ import android.os.ParcelUuid;
// Based on http://stanford.edu/~tpurtell/InsecureBluetooth.java by T.J. Purtell // Based on http://stanford.edu/~tpurtell/InsecureBluetooth.java by T.J. Purtell
class InsecureBluetooth { class InsecureBluetooth {
private static final Logger LOG =
Logger.getLogger(InsecureBluetooth.class.getName());
private static final int TYPE_RFCOMM = 1; private static final int TYPE_RFCOMM = 1;
@SuppressLint("NewApi") @SuppressLint("NewApi")
static BluetoothServerSocket listen(BluetoothAdapter adapter, String name, static BluetoothServerSocket listen(BluetoothAdapter adapter, String name,
UUID uuid) throws IOException { UUID uuid) throws IOException {
if(Build.VERSION.SDK_INT >= 10) { if(Build.VERSION.SDK_INT >= 10) {
if(LOG.isLoggable(INFO)) LOG.info("Listening with new API");
return adapter.listenUsingInsecureRfcommWithServiceRecord(name, return adapter.listenUsingInsecureRfcommWithServiceRecord(name,
uuid); uuid);
} }
try { try {
if(LOG.isLoggable(INFO)) LOG.info("Listening via reflection");
// Find an available channel
String className = BluetoothAdapter.class.getName() String className = BluetoothAdapter.class.getName()
+ ".RfcommChannelPicker"; + ".RfcommChannelPicker";
Class<?> channelPickerClass = null; Class<?> channelPickerClass = null;
...@@ -48,15 +57,15 @@ class InsecureBluetooth { ...@@ -48,15 +57,15 @@ class InsecureBluetooth {
if(constructor == null) if(constructor == null)
throw new IOException("Can't find channel picker constructor"); throw new IOException("Can't find channel picker constructor");
Object channelPicker = constructor.newInstance(uuid); Object channelPicker = constructor.newInstance(uuid);
Method nextChannel = channelPickerClass.getDeclaredMethod( Method nextChannel =
"nextChannel", new Class[0]); channelPickerClass.getDeclaredMethod("nextChannel");
nextChannel.setAccessible(true); nextChannel.setAccessible(true);
BluetoothServerSocket socket = null; int channel = (Integer) nextChannel.invoke(channelPicker);
int channel = (Integer) nextChannel.invoke(channelPicker,
new Object[0]);
if(channel == -1) throw new IOException("No available channels"); if(channel == -1) throw new IOException("No available channels");
socket = listen(channel); // Listen on the channel
Field f = adapter.getClass().getDeclaredField("mService"); BluetoothServerSocket socket = listen(channel);
// Add a service record
Field f = BluetoothAdapter.class.getDeclaredField("mService");
f.setAccessible(true); f.setAccessible(true);
Object mService = f.get(adapter); Object mService = f.get(adapter);
Method addRfcommServiceRecord = Method addRfcommServiceRecord =
...@@ -70,7 +79,7 @@ class InsecureBluetooth { ...@@ -70,7 +79,7 @@ class InsecureBluetooth {
socket.close(); socket.close();
throw new IOException("Can't register SDP record for " + name); throw new IOException("Can't register SDP record for " + name);
} }
Field f1 = adapter.getClass().getDeclaredField("mHandler"); Field f1 = BluetoothAdapter.class.getDeclaredField("mHandler");
f1.setAccessible(true); f1.setAccessible(true);
Object mHandler = f1.get(adapter); Object mHandler = f1.get(adapter);
Method setCloseHandler = socket.getClass().getDeclaredMethod( Method setCloseHandler = socket.getClass().getDeclaredMethod(
...@@ -96,7 +105,6 @@ class InsecureBluetooth { ...@@ -96,7 +105,6 @@ class InsecureBluetooth {
} }
private static BluetoothServerSocket listen(int port) throws IOException { private static BluetoothServerSocket listen(int port) throws IOException {
BluetoothServerSocket socket = null;
try { try {
Constructor<BluetoothServerSocket> constructor = Constructor<BluetoothServerSocket> constructor =
BluetoothServerSocket.class.getDeclaredConstructor( BluetoothServerSocket.class.getDeclaredConstructor(
...@@ -104,15 +112,15 @@ class InsecureBluetooth { ...@@ -104,15 +112,15 @@ class InsecureBluetooth {
if(constructor == null) if(constructor == null)
throw new IOException("Can't find server socket constructor"); throw new IOException("Can't find server socket constructor");
constructor.setAccessible(true); constructor.setAccessible(true);
socket = constructor.newInstance(TYPE_RFCOMM, false, false, port); BluetoothServerSocket socket = constructor.newInstance(TYPE_RFCOMM,
Field f = socket.getClass().getDeclaredField("mSocket"); false, false, port);
Field f = BluetoothServerSocket.class.getDeclaredField("mSocket");
f.setAccessible(true); f.setAccessible(true);
Object mSocket = f.get(socket); Object mSocket = f.get(socket);
Method bindListen = mSocket.getClass().getDeclaredMethod( Method bindListen =
"bindListen", new Class[0]); mSocket.getClass().getDeclaredMethod("bindListen");
bindListen.setAccessible(true); bindListen.setAccessible(true);
Object result = bindListen.invoke(mSocket, new Object[0]); int errno = (Integer) bindListen.invoke(mSocket);
int errno = (Integer) result;
if(errno != 0) { if(errno != 0) {
socket.close(); socket.close();
throw new IOException("Can't bind: errno " + errno); throw new IOException("Can't bind: errno " + errno);
...@@ -138,10 +146,12 @@ class InsecureBluetooth { ...@@ -138,10 +146,12 @@ class InsecureBluetooth {
@SuppressLint("NewApi") @SuppressLint("NewApi")
static BluetoothSocket createSocket(BluetoothDevice device, UUID uuid) static BluetoothSocket createSocket(BluetoothDevice device, UUID uuid)
throws IOException { throws IOException {
if(Build.VERSION.SDK_INT >= 10) if(Build.VERSION.SDK_INT >= 10) {
if(LOG.isLoggable(INFO)) LOG.info("Creating socket with new API");
return device.createInsecureRfcommSocketToServiceRecord(uuid); return device.createInsecureRfcommSocketToServiceRecord(uuid);
}
try { try {
BluetoothSocket socket = null; if(LOG.isLoggable(INFO)) LOG.info("Creating socket via reflection");
Constructor<BluetoothSocket> constructor = Constructor<BluetoothSocket> constructor =
BluetoothSocket.class.getDeclaredConstructor(int.class, BluetoothSocket.class.getDeclaredConstructor(int.class,
int.class, boolean.class, boolean.class, int.class, boolean.class, boolean.class,
...@@ -149,9 +159,8 @@ class InsecureBluetooth { ...@@ -149,9 +159,8 @@ class InsecureBluetooth {
if(constructor == null) if(constructor == null)
throw new IOException("Can't find socket constructor"); throw new IOException("Can't find socket constructor");
constructor.setAccessible(true); constructor.setAccessible(true);
socket = constructor.newInstance(TYPE_RFCOMM, -1, false, true, return constructor.newInstance(TYPE_RFCOMM, -1, false, true, device,
device, -1, uuid != null ? new ParcelUuid(uuid) : null); -1, new ParcelUuid(uuid));
return socket;
} catch(NoSuchMethodException e) { } catch(NoSuchMethodException e) {
throw new IOException(e.toString()); throw new IOException(e.toString());
} catch(IllegalAccessException e) { } catch(IllegalAccessException e) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment