Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c88b0c62 authored by Jaikumar Ganesh's avatar Jaikumar Ganesh
Browse files

Follow the spec recommendation for keyboard pairing.

Generate a variable pin and show it to the user.

Change-Id: Id4aae7a16f25c67d6c6ead6fd936cb14087f3c7a
parent 0a53d5c8
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -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;
    }

    /**
+90 −35
Original line number Diff line number Diff line
@@ -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

    /**
     * A bond attempt failed because we received an Authentication Cancel
     * by remote end
     * @hide */
     * @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
+29 −5
Original line number Diff line number Diff line
@@ -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;