am 32d8571f: Changes for BT 2.1
Merge commit '32d8571f509c392dca732c243e9b2138c15daecf' into eclair-plus-aosp * commit '32d8571f509c392dca732c243e9b2138c15daecf': Changes for BT 2.1
This commit is contained in:
@@ -250,7 +250,7 @@ public final class BluetoothDevice implements Parcelable {
|
||||
* @hide */
|
||||
public static final int BOND_SUCCESS = 0;
|
||||
/** A bond attempt failed because pins did not match, or remote device did
|
||||
* not respond to pin request in time
|
||||
* not respond to pin request in time
|
||||
* @hide */
|
||||
public static final int UNBOND_REASON_AUTH_FAILED = 1;
|
||||
/** A bond attempt failed because the other side explicilty rejected
|
||||
@@ -266,9 +266,15 @@ public final class BluetoothDevice implements Parcelable {
|
||||
/** A bond attempt failed because a discovery is in progress
|
||||
* @hide */
|
||||
public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
|
||||
/** A bond attempt failed because of authentication timeout
|
||||
* @hide */
|
||||
public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
|
||||
/** A bond attempt failed because of repeated attempts
|
||||
* @hide */
|
||||
public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
|
||||
/** An existing bond was explicitly revoked
|
||||
* @hide */
|
||||
public static final int UNBOND_REASON_REMOVED = 6;
|
||||
public static final int UNBOND_REASON_REMOVED = 8;
|
||||
|
||||
/** The user will be prompted to enter a pin
|
||||
* @hide */
|
||||
@@ -278,7 +284,13 @@ public final class BluetoothDevice implements Parcelable {
|
||||
public static final int PAIRING_VARIANT_PASSKEY = 1;
|
||||
/** The user will be prompted to confirm the passkey displayed on the screen
|
||||
* @hide */
|
||||
public static final int PAIRING_VARIANT_CONFIRMATION = 2;
|
||||
public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
|
||||
/** The user will be prompted to accept or deny the incoming pairing request
|
||||
* @hide */
|
||||
public static final int PAIRING_VARIANT_CONSENT = 3;
|
||||
/** The user will be prompted to enter the passkey displayed on remote device
|
||||
* @hide */
|
||||
public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
|
||||
|
||||
private static IBluetooth sService; /* Guarenteed constant after first object constructed */
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
package android.server;
|
||||
|
||||
import android.bluetooth.BluetoothA2dp;
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothUuid;
|
||||
import android.content.Context;
|
||||
@@ -53,6 +53,7 @@ class BluetoothEventLoop {
|
||||
|
||||
private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
|
||||
private static final int EVENT_RESTART_BLUETOOTH = 2;
|
||||
private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 3;
|
||||
|
||||
// The time (in millisecs) to delay the pairing attempt after the first
|
||||
// auto pairing attempt fails. We use an exponential delay with
|
||||
@@ -67,9 +68,10 @@ class BluetoothEventLoop {
|
||||
private final Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
String address = null;
|
||||
switch (msg.what) {
|
||||
case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
|
||||
String address = (String)msg.obj;
|
||||
address = (String)msg.obj;
|
||||
if (address != null) {
|
||||
mBluetoothService.createBond(address);
|
||||
return;
|
||||
@@ -78,6 +80,12 @@ class BluetoothEventLoop {
|
||||
case EVENT_RESTART_BLUETOOTH:
|
||||
mBluetoothService.restart();
|
||||
break;
|
||||
case EVENT_PAIRING_CONSENT_DELAYED_ACCEPT:
|
||||
address = (String)msg.obj;
|
||||
if (address != null) {
|
||||
mBluetoothService.setPairingConfirmation(address, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -239,6 +247,7 @@ class BluetoothEventLoop {
|
||||
addDevice(address, properties);
|
||||
}
|
||||
}
|
||||
mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDING);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -390,7 +399,32 @@ class BluetoothEventLoop {
|
||||
return address;
|
||||
}
|
||||
|
||||
private void onRequestConfirmation(String objectPath, int passkey, int nativeData) {
|
||||
private void onRequestPairingConsent(String objectPath, int nativeData) {
|
||||
String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
|
||||
if (address == null) return;
|
||||
|
||||
/* The link key will not be stored if the incoming request has MITM
|
||||
* protection switched on. Unfortunately, some devices have MITM
|
||||
* switched on even though their capabilities are NoInputNoOutput,
|
||||
* so we may get this request many times. Also if we respond immediately,
|
||||
* the other end is unable to handle it. Delay sending the message.
|
||||
*/
|
||||
if (mBluetoothService.getBondState().getBondState(address) == BluetoothDevice.BOND_BONDED) {
|
||||
Message message = mHandler.obtainMessage(EVENT_PAIRING_CONSENT_DELAYED_ACCEPT);
|
||||
message.obj = address;
|
||||
mHandler.sendMessageDelayed(message, 1500);
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
|
||||
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
|
||||
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
|
||||
BluetoothDevice.PAIRING_VARIANT_CONSENT);
|
||||
mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
|
||||
return;
|
||||
}
|
||||
|
||||
private void onRequestPasskeyConfirmation(String objectPath, int passkey, int nativeData) {
|
||||
String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
|
||||
if (address == null) return;
|
||||
|
||||
@@ -398,7 +432,7 @@ class BluetoothEventLoop {
|
||||
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
|
||||
intent.putExtra(BluetoothDevice.EXTRA_PASSKEY, passkey);
|
||||
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
|
||||
BluetoothDevice.PAIRING_VARIANT_CONFIRMATION);
|
||||
BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION);
|
||||
mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
|
||||
return;
|
||||
}
|
||||
@@ -447,6 +481,18 @@ class BluetoothEventLoop {
|
||||
return;
|
||||
}
|
||||
|
||||
private void onDisplayPasskey(String objectPath, int passkey, int nativeData) {
|
||||
String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
|
||||
if (address == null) return;
|
||||
|
||||
Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
|
||||
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
|
||||
intent.putExtra(BluetoothDevice.EXTRA_PASSKEY, passkey);
|
||||
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
|
||||
BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY);
|
||||
mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
|
||||
}
|
||||
|
||||
private boolean onAgentAuthorize(String objectPath, String deviceUuid) {
|
||||
String address = mBluetoothService.getAddressFromObjectPath(objectPath);
|
||||
if (address == null) {
|
||||
|
||||
@@ -1266,5 +1266,4 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
private native boolean setPairingConfirmationNative(String address, boolean confirm,
|
||||
int nativeData);
|
||||
private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value);
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +52,9 @@ static jmethodID method_onGetDeviceServiceChannelResult;
|
||||
|
||||
static jmethodID method_onRequestPinCode;
|
||||
static jmethodID method_onRequestPasskey;
|
||||
static jmethodID method_onRequestConfirmation;
|
||||
static jmethodID method_onRequestPasskeyConfirmation;
|
||||
static jmethodID method_onRequestPairingConsent;
|
||||
static jmethodID method_onDisplayPasskey;
|
||||
static jmethodID method_onAgentAuthorize;
|
||||
static jmethodID method_onAgentCancel;
|
||||
|
||||
@@ -98,7 +100,11 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
|
||||
"(Ljava/lang/String;I)V");
|
||||
method_onRequestPasskey = env->GetMethodID(clazz, "onRequestPasskey",
|
||||
"(Ljava/lang/String;I)V");
|
||||
method_onRequestConfirmation = env->GetMethodID(clazz, "onRequestConfirmation",
|
||||
method_onRequestPasskeyConfirmation = env->GetMethodID(clazz, "onRequestPasskeyConfirmation",
|
||||
"(Ljava/lang/String;II)V");
|
||||
method_onRequestPairingConsent = env->GetMethodID(clazz, "onRequestPairingConsent",
|
||||
"(Ljava/lang/String;I)V");
|
||||
method_onDisplayPasskey = env->GetMethodID(clazz, "onDisplayPasskey",
|
||||
"(Ljava/lang/String;II)V");
|
||||
|
||||
field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I");
|
||||
@@ -230,7 +236,7 @@ static jboolean setUpEventLoop(native_data_t *nat) {
|
||||
|
||||
|
||||
const char * get_adapter_path(DBusConnection *conn) {
|
||||
DBusMessage *msg, *reply = NULL;
|
||||
DBusMessage *msg = NULL, *reply = NULL;
|
||||
DBusError err;
|
||||
const char *device_path = NULL;
|
||||
int attempt = 0;
|
||||
@@ -856,9 +862,7 @@ DBusHandlerResult agent_event_filter(DBusConnection *conn,
|
||||
|
||||
if (dbus_message_is_method_call(msg,
|
||||
"org.bluez.Agent", "Cancel")) {
|
||||
|
||||
env->CallVoidMethod(nat->me, method_onAgentCancel);
|
||||
|
||||
// reply
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
if (!reply) {
|
||||
@@ -938,6 +942,24 @@ DBusHandlerResult agent_event_filter(DBusConnection *conn,
|
||||
env->NewStringUTF(object_path),
|
||||
int(msg));
|
||||
goto success;
|
||||
} else if (dbus_message_is_method_call(msg,
|
||||
"org.bluez.Agent", "DisplayPasskey")) {
|
||||
char *object_path;
|
||||
uint32_t passkey;
|
||||
if (!dbus_message_get_args(msg, NULL,
|
||||
DBUS_TYPE_OBJECT_PATH, &object_path,
|
||||
DBUS_TYPE_UINT32, &passkey,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
LOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
dbus_message_ref(msg); // increment refcount because we pass to java
|
||||
env->CallVoidMethod(nat->me, method_onDisplayPasskey,
|
||||
env->NewStringUTF(object_path),
|
||||
passkey,
|
||||
int(msg));
|
||||
goto success;
|
||||
} else if (dbus_message_is_method_call(msg,
|
||||
"org.bluez.Agent", "RequestConfirmation")) {
|
||||
char *object_path;
|
||||
@@ -951,11 +973,26 @@ DBusHandlerResult agent_event_filter(DBusConnection *conn,
|
||||
}
|
||||
|
||||
dbus_message_ref(msg); // increment refcount because we pass to java
|
||||
env->CallVoidMethod(nat->me, method_onRequestConfirmation,
|
||||
env->CallVoidMethod(nat->me, method_onRequestPasskeyConfirmation,
|
||||
env->NewStringUTF(object_path),
|
||||
passkey,
|
||||
int(msg));
|
||||
goto success;
|
||||
} else if (dbus_message_is_method_call(msg,
|
||||
"org.bluez.Agent", "RequestPairingConsent")) {
|
||||
char *object_path;
|
||||
if (!dbus_message_get_args(msg, NULL,
|
||||
DBUS_TYPE_OBJECT_PATH, &object_path,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
LOGE("%s: Invalid arguments for RequestPairingConsent() method", __FUNCTION__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
dbus_message_ref(msg); // increment refcount because we pass to java
|
||||
env->CallVoidMethod(nat->me, method_onRequestPairingConsent,
|
||||
env->NewStringUTF(object_path),
|
||||
int(msg));
|
||||
goto success;
|
||||
} else if (dbus_message_is_method_call(msg,
|
||||
"org.bluez.Agent", "Release")) {
|
||||
// reply
|
||||
@@ -992,6 +1029,8 @@ success:
|
||||
#define BOND_RESULT_AUTH_CANCELED 3
|
||||
#define BOND_RESULT_REMOTE_DEVICE_DOWN 4
|
||||
#define BOND_RESULT_DISCOVERY_IN_PROGRESS 5
|
||||
#define BOND_RESULT_AUTH_TIMEOUT 6
|
||||
#define BOND_RESULT_REPEATED_ATTEMPTS 7
|
||||
|
||||
void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
|
||||
LOGV(__FUNCTION__);
|
||||
@@ -1037,6 +1076,12 @@ void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
|
||||
!strcmp(err.message, "Discover in progress")) {
|
||||
LOGV("... error = %s (%s)\n", err.name, err.message);
|
||||
result = BOND_RESULT_DISCOVERY_IN_PROGRESS;
|
||||
} else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.RepeatedAttempts")) {
|
||||
LOGV("... error = %s (%s)\n", err.name, err.message);
|
||||
result = BOND_RESULT_REPEATED_ATTEMPTS;
|
||||
} else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationTimeout")) {
|
||||
LOGV("... error = %s (%s)\n", err.name, err.message);
|
||||
result = BOND_RESULT_AUTH_TIMEOUT;
|
||||
} else {
|
||||
LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
|
||||
result = BOND_RESULT_ERROR;
|
||||
|
||||
@@ -455,8 +455,8 @@ static jboolean setPairingConfirmationNative(JNIEnv *env, jobject object,
|
||||
}
|
||||
|
||||
if (!reply) {
|
||||
LOGE("%s: Cannot create message reply to RequestConfirmation to "
|
||||
"D-Bus\n", __FUNCTION__);
|
||||
LOGE("%s: Cannot create message reply to RequestPasskeyConfirmation or"
|
||||
"RequestPairingConsent to D-Bus\n", __FUNCTION__);
|
||||
dbus_message_unref(msg);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user