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 */
|
* @hide */
|
||||||
public static final int BOND_SUCCESS = 0;
|
public static final int BOND_SUCCESS = 0;
|
||||||
/** A bond attempt failed because pins did not match, or remote device did
|
/** 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 */
|
* @hide */
|
||||||
public static final int UNBOND_REASON_AUTH_FAILED = 1;
|
public static final int UNBOND_REASON_AUTH_FAILED = 1;
|
||||||
/** A bond attempt failed because the other side explicilty rejected
|
/** 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
|
/** A bond attempt failed because a discovery is in progress
|
||||||
* @hide */
|
* @hide */
|
||||||
public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
|
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
|
/** An existing bond was explicitly revoked
|
||||||
* @hide */
|
* @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
|
/** The user will be prompted to enter a pin
|
||||||
* @hide */
|
* @hide */
|
||||||
@@ -278,7 +284,13 @@ public final class BluetoothDevice implements Parcelable {
|
|||||||
public static final int PAIRING_VARIANT_PASSKEY = 1;
|
public static final int PAIRING_VARIANT_PASSKEY = 1;
|
||||||
/** The user will be prompted to confirm the passkey displayed on the screen
|
/** The user will be prompted to confirm the passkey displayed on the screen
|
||||||
* @hide */
|
* @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 */
|
private static IBluetooth sService; /* Guarenteed constant after first object constructed */
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
package android.server;
|
package android.server;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothA2dp;
|
import android.bluetooth.BluetoothA2dp;
|
||||||
import android.bluetooth.BluetoothClass;
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothClass;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothUuid;
|
import android.bluetooth.BluetoothUuid;
|
||||||
import android.content.Context;
|
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_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
|
||||||
private static final int EVENT_RESTART_BLUETOOTH = 2;
|
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
|
// The time (in millisecs) to delay the pairing attempt after the first
|
||||||
// auto pairing attempt fails. We use an exponential delay with
|
// auto pairing attempt fails. We use an exponential delay with
|
||||||
@@ -67,9 +68,10 @@ class BluetoothEventLoop {
|
|||||||
private final Handler mHandler = new Handler() {
|
private final Handler mHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
|
String address = null;
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
|
case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
|
||||||
String address = (String)msg.obj;
|
address = (String)msg.obj;
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
mBluetoothService.createBond(address);
|
mBluetoothService.createBond(address);
|
||||||
return;
|
return;
|
||||||
@@ -78,6 +80,12 @@ class BluetoothEventLoop {
|
|||||||
case EVENT_RESTART_BLUETOOTH:
|
case EVENT_RESTART_BLUETOOTH:
|
||||||
mBluetoothService.restart();
|
mBluetoothService.restart();
|
||||||
break;
|
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);
|
addDevice(address, properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDING);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,7 +399,32 @@ class BluetoothEventLoop {
|
|||||||
return address;
|
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);
|
String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
|
||||||
if (address == null) return;
|
if (address == null) return;
|
||||||
|
|
||||||
@@ -398,7 +432,7 @@ class BluetoothEventLoop {
|
|||||||
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
|
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
|
||||||
intent.putExtra(BluetoothDevice.EXTRA_PASSKEY, passkey);
|
intent.putExtra(BluetoothDevice.EXTRA_PASSKEY, passkey);
|
||||||
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
|
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
|
||||||
BluetoothDevice.PAIRING_VARIANT_CONFIRMATION);
|
BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION);
|
||||||
mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
|
mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -447,6 +481,18 @@ class BluetoothEventLoop {
|
|||||||
return;
|
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) {
|
private boolean onAgentAuthorize(String objectPath, String deviceUuid) {
|
||||||
String address = mBluetoothService.getAddressFromObjectPath(objectPath);
|
String address = mBluetoothService.getAddressFromObjectPath(objectPath);
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
|
|||||||
@@ -1266,5 +1266,4 @@ public class BluetoothService extends IBluetooth.Stub {
|
|||||||
private native boolean setPairingConfirmationNative(String address, boolean confirm,
|
private native boolean setPairingConfirmationNative(String address, boolean confirm,
|
||||||
int nativeData);
|
int nativeData);
|
||||||
private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value);
|
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_onRequestPinCode;
|
||||||
static jmethodID method_onRequestPasskey;
|
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_onAgentAuthorize;
|
||||||
static jmethodID method_onAgentCancel;
|
static jmethodID method_onAgentCancel;
|
||||||
|
|
||||||
@@ -98,7 +100,11 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
|
|||||||
"(Ljava/lang/String;I)V");
|
"(Ljava/lang/String;I)V");
|
||||||
method_onRequestPasskey = env->GetMethodID(clazz, "onRequestPasskey",
|
method_onRequestPasskey = env->GetMethodID(clazz, "onRequestPasskey",
|
||||||
"(Ljava/lang/String;I)V");
|
"(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");
|
"(Ljava/lang/String;II)V");
|
||||||
|
|
||||||
field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I");
|
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) {
|
const char * get_adapter_path(DBusConnection *conn) {
|
||||||
DBusMessage *msg, *reply = NULL;
|
DBusMessage *msg = NULL, *reply = NULL;
|
||||||
DBusError err;
|
DBusError err;
|
||||||
const char *device_path = NULL;
|
const char *device_path = NULL;
|
||||||
int attempt = 0;
|
int attempt = 0;
|
||||||
@@ -856,9 +862,7 @@ DBusHandlerResult agent_event_filter(DBusConnection *conn,
|
|||||||
|
|
||||||
if (dbus_message_is_method_call(msg,
|
if (dbus_message_is_method_call(msg,
|
||||||
"org.bluez.Agent", "Cancel")) {
|
"org.bluez.Agent", "Cancel")) {
|
||||||
|
|
||||||
env->CallVoidMethod(nat->me, method_onAgentCancel);
|
env->CallVoidMethod(nat->me, method_onAgentCancel);
|
||||||
|
|
||||||
// reply
|
// reply
|
||||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
@@ -938,6 +942,24 @@ DBusHandlerResult agent_event_filter(DBusConnection *conn,
|
|||||||
env->NewStringUTF(object_path),
|
env->NewStringUTF(object_path),
|
||||||
int(msg));
|
int(msg));
|
||||||
goto success;
|
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,
|
} else if (dbus_message_is_method_call(msg,
|
||||||
"org.bluez.Agent", "RequestConfirmation")) {
|
"org.bluez.Agent", "RequestConfirmation")) {
|
||||||
char *object_path;
|
char *object_path;
|
||||||
@@ -951,11 +973,26 @@ DBusHandlerResult agent_event_filter(DBusConnection *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbus_message_ref(msg); // increment refcount because we pass to java
|
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),
|
env->NewStringUTF(object_path),
|
||||||
passkey,
|
passkey,
|
||||||
int(msg));
|
int(msg));
|
||||||
goto success;
|
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,
|
} else if (dbus_message_is_method_call(msg,
|
||||||
"org.bluez.Agent", "Release")) {
|
"org.bluez.Agent", "Release")) {
|
||||||
// reply
|
// reply
|
||||||
@@ -992,6 +1029,8 @@ success:
|
|||||||
#define BOND_RESULT_AUTH_CANCELED 3
|
#define BOND_RESULT_AUTH_CANCELED 3
|
||||||
#define BOND_RESULT_REMOTE_DEVICE_DOWN 4
|
#define BOND_RESULT_REMOTE_DEVICE_DOWN 4
|
||||||
#define BOND_RESULT_DISCOVERY_IN_PROGRESS 5
|
#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) {
|
void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
|
||||||
LOGV(__FUNCTION__);
|
LOGV(__FUNCTION__);
|
||||||
@@ -1037,6 +1076,12 @@ void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
|
|||||||
!strcmp(err.message, "Discover in progress")) {
|
!strcmp(err.message, "Discover in progress")) {
|
||||||
LOGV("... error = %s (%s)\n", err.name, err.message);
|
LOGV("... error = %s (%s)\n", err.name, err.message);
|
||||||
result = BOND_RESULT_DISCOVERY_IN_PROGRESS;
|
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 {
|
} else {
|
||||||
LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
|
LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
|
||||||
result = BOND_RESULT_ERROR;
|
result = BOND_RESULT_ERROR;
|
||||||
|
|||||||
@@ -455,8 +455,8 @@ static jboolean setPairingConfirmationNative(JNIEnv *env, jobject object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
LOGE("%s: Cannot create message reply to RequestConfirmation to "
|
LOGE("%s: Cannot create message reply to RequestPasskeyConfirmation or"
|
||||||
"D-Bus\n", __FUNCTION__);
|
"RequestPairingConsent to D-Bus\n", __FUNCTION__);
|
||||||
dbus_message_unref(msg);
|
dbus_message_unref(msg);
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user