diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java index e604e6becc9bf..54bf4afa93ffb 100644 --- a/core/java/android/bluetooth/BluetoothClass.java +++ b/core/java/android/bluetooth/BluetoothClass.java @@ -226,6 +226,24 @@ public final class BluetoothClass implements Parcelable { public static final int HEALTH_PULSE_OXIMETER = 0x0914; public static final int HEALTH_PULSE_RATE = 0x0918; public static final int HEALTH_DATA_DISPLAY = 0x091C; + + // Devices in PERIPHERAL major class + /** + * @hide + */ + public static final int PERIPHERAL_NON_KEYBOARD_NON_POINTING = 0x0500; + /** + * @hide + */ + public static final int PERIPHERAL_KEYBOARD = 0x0540; + /** + * @hide + */ + public static final int PERIPHERAL_POINTING = 0x0580; + /** + * @hide + */ + public static final int PERIPHERAL_KEYBOARD_POINTING = 0x05C0; } /** diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index e15d003114779..24217d7dc011d 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -239,7 +239,7 @@ public final class BluetoothDevice implements Parcelable { public static final String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT"; /** @hide */ - public static final String EXTRA_PASSKEY = "android.bluetooth.device.extra.PASSKEY"; + public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY"; /** * Broadcast Action: This intent is used to broadcast the {@link UUID} @@ -276,58 +276,113 @@ public final class BluetoothDevice implements Parcelable { public static final String ACTION_PAIRING_CANCEL = "android.bluetooth.device.action.PAIRING_CANCEL"; - /** A bond attempt succeeded - * @hide */ + /** + * A bond attempt succeeded + * @hide + */ 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 - * @hide */ + * @hide + */ public static final int UNBOND_REASON_AUTH_FAILED = 1; - /** A bond attempt failed because the other side explicitly rejected + + /** + * A bond attempt failed because the other side explicitly rejected * bonding - * @hide */ + * @hide + */ public static final int UNBOND_REASON_AUTH_REJECTED = 2; - /** A bond attempt failed because we canceled the bonding process - * @hide */ + + /** + * A bond attempt failed because we canceled the bonding process + * @hide + */ public static final int UNBOND_REASON_AUTH_CANCELED = 3; - /** A bond attempt failed because we could not contact the remote device - * @hide */ + + /** + * A bond attempt failed because we could not contact the remote device + * @hide + */ public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4; - /** A bond attempt failed because a discovery is in progress - * @hide */ + + /** + * 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 */ + + /** + * 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 */ + + /** + * A bond attempt failed because of repeated attempts + * @hide + */ public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7; - /** A bond attempt failed because we received an Authentication Cancel - * by remote end - * @hide */ + + /** + * A bond attempt failed because we received an Authentication Cancel + * by remote end + * @hide + */ public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8; - /** An existing bond was explicitly revoked - * @hide */ + + /** + * An existing bond was explicitly revoked + * @hide + */ public static final int UNBOND_REASON_REMOVED = 9; - /** The user will be prompted to enter a pin - * @hide */ + /** + * The user will be prompted to enter a pin + * @hide + */ public static final int PAIRING_VARIANT_PIN = 0; - /** The user will be prompted to enter a passkey - * @hide */ + + /** + * The user will be prompted to enter a passkey + * @hide + */ public static final int PAIRING_VARIANT_PASSKEY = 1; - /** The user will be prompted to confirm the passkey displayed on the screen - * @hide */ + + /** + * The user will be prompted to confirm the passkey displayed on the screen + * @hide + */ public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; - /** The user will be prompted to accept or deny the incoming pairing request - * @hide */ + + /** + * 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 */ + + /** + * The user will be prompted to enter the passkey displayed on remote device + * This is used for Bluetooth 2.1 pairing. + * @hide + */ public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4; - /** The user will be prompted to accept or deny the OOB pairing request - * @hide */ - public static final int PAIRING_VARIANT_OOB_CONSENT = 5; + + /** + * The user will be prompted to enter the PIN displayed on remote device. + * This is used for Bluetooth 2.0 pairing. + * @hide + */ + public static final int PAIRING_VARIANT_DISPLAY_PIN = 5; + + /** + * The user will be prompted to accept or deny the OOB pairing request + * @hide + */ + public static final int PAIRING_VARIANT_OOB_CONSENT = 6; + /** * Used as an extra field in {@link #ACTION_UUID} intents, * Contains the {@link android.os.ParcelUuid}s of the remote device which diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index c04bb52c8e9d5..ebe7d32361b20 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -493,7 +493,7 @@ class BluetoothEventLoop { mWakeLock.acquire(); 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_KEY, passkey); intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); @@ -523,6 +523,9 @@ class BluetoothEventLoop { String pendingOutgoingAddress = mBluetoothService.getPendingOutgoingBonding(); + BluetoothClass btClass = new BluetoothClass(mBluetoothService.getRemoteClass(address)); + int btDeviceClass = btClass.getDeviceClass(); + if (address.equals(pendingOutgoingAddress)) { // we initiated the bonding @@ -533,10 +536,8 @@ class BluetoothEventLoop { return; } - BluetoothClass btClass = new BluetoothClass(mBluetoothService.getRemoteClass(address)); - // try 0000 once if the device looks dumb - switch (btClass.getDeviceClass()) { + switch (btDeviceClass) { case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES: @@ -546,6 +547,16 @@ class BluetoothEventLoop { if (mBluetoothService.attemptAutoPair(address)) return; } } + + if (btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD || + btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING) { + // Its a keyboard. Follow the HID spec recommendation of creating the + // passkey and displaying it to the user. + // Generate a variable PIN. This is not truly random but good enough. + int pin = (int) Math.floor(Math.random() * 10000); + sendDisplayPinIntent(address, pin); + return; + } // Acquire wakelock during PIN code request to bring up LCD display mWakeLock.acquire(); Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); @@ -565,7 +576,7 @@ class BluetoothEventLoop { mWakeLock.acquire(); 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_KEY, passkey); intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); @@ -573,6 +584,19 @@ class BluetoothEventLoop { mWakeLock.release(); } + private void sendDisplayPinIntent(String address, int pin) { + // Acquire wakelock during PIN code request to bring up LCD display + mWakeLock.acquire(); + Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); + intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin); + intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, + BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN); + mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); + //Release wakelock to allow the LCD to go off after the PIN popup notifcation. + mWakeLock.release(); + } + private void onRequestOobData(String objectPath , int nativeData) { String address = checkPairingRequestAndGetAddress(objectPath, nativeData); if (address == null) return;