mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 12:49:55 +01:00
Cleaned up Android Bluetooth reflection code and added logging.
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
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;
|
|||||||
// 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
@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 {
|
|||||||
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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user