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

Commit 3bb4e188 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

Enable HID Device Profile Service (2/2)

Add Profile Proxy for HID Device Profile.

* Add a helper method doUnbind() to deal with unbinding to Bluetooth HID
Service.

* Fix docstrings.

Bug: 63384609
Test: SL4A Bluetooth HID test
Change-Id: I168c21c3b010baac9889c556635b914c0ba3f267
parent ee1e6329
Loading
Loading
Loading
Loading
+38 −33
Original line number Diff line number Diff line
@@ -31,7 +31,14 @@ import java.util.Arrays;
import java.util.List;

/**
 * @hide
 * Provides the public APIs to control the Bluetooth HID Device
 * profile.
 *
 * BluetoothHidDevice is a proxy object for controlling the Bluetooth HID
 * Device Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
 * the BluetoothHidDevice proxy object.
 *
 * {@hide}
 */
public final class BluetoothHidDevice implements BluetoothProfile {

@@ -62,7 +69,9 @@ public final class BluetoothHidDevice implements BluetoothProfile {
    /**
     * Constants representing device subclass.
     *
     * @see #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)
     * @see #registerApp
     * (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
     * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)
     */
    public static final byte SUBCLASS1_NONE = (byte) 0x00;
    public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
@@ -80,9 +89,9 @@ public final class BluetoothHidDevice implements BluetoothProfile {
    /**
     * Constants representing report types.
     *
     * @see BluetoothHidDeviceCallback#onGetReport(byte, byte, int)
     * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])
     * @see BluetoothHidDeviceCallback#onIntrData(byte, byte[])
     * @see BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)
     * @see BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])
     * @see BluetoothHidDeviceCallback#onIntrData(BluetoothDevice, byte, byte[])
     */
    public static final byte REPORT_TYPE_INPUT = (byte) 1;
    public static final byte REPORT_TYPE_OUTPUT = (byte) 2;
@@ -91,7 +100,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
    /**
     * Constants representing error response for Set Report.
     *
     * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])
     * @see BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])
     */
    public static final byte ERROR_RSP_SUCCESS = (byte) 0;
    public static final byte ERROR_RSP_NOT_READY = (byte) 1;
@@ -104,7 +113,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
     * Constants representing protocol mode used set by host. Default is always
     * {@link #PROTOCOL_REPORT_MODE} unless notified otherwise.
     *
     * @see BluetoothHidDeviceCallback#onSetProtocol(byte)
     * @see BluetoothHidDeviceCallback#onSetProtocol(BluetoothDevice, byte)
     */
    public static final byte PROTOCOL_BOOT_MODE = (byte) 0;
    public static final byte PROTOCOL_REPORT_MODE = (byte) 1;
@@ -169,18 +178,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
                public void onBluetoothStateChange(boolean up) {
                    Log.d(TAG, "onBluetoothStateChange: up=" + up);
                    synchronized (mConnection) {
                        if (!up) {
                            Log.d(TAG, "Unbinding service...");
                            if (mService != null) {
                                mService = null;
                                try {
                                    mContext.unbindService(mConnection);
                                } catch (IllegalArgumentException e) {
                                    Log.e(TAG, "onBluetoothStateChange: could not unbind service:",
                                            e);
                                }
                            }
                        } else {
                        if (up) {
                            try {
                                if (mService == null) {
                                    Log.d(TAG, "Binding HID Device service...");
@@ -189,14 +187,15 @@ public final class BluetoothHidDevice implements BluetoothProfile {
                            } catch (IllegalStateException e) {
                                Log.e(TAG,
                                        "onBluetoothStateChange: could not bind to HID Dev "
                                                + "service: ",
                                        e);
                                                + "service: ", e);
                            } catch (SecurityException e) {
                                Log.e(TAG,
                                        "onBluetoothStateChange: could not bind to HID Dev "
                                                + "service: ",
                                        e);
                                                + "service: ", e);
                            }
                        } else {
                            Log.d(TAG, "Unbinding service...");
                            doUnbind();
                        }
                    }
                }
@@ -252,6 +251,18 @@ public final class BluetoothHidDevice implements BluetoothProfile {
        return true;
    }

    void doUnbind() {
        Log.d(TAG, "Unbinding HidDevService");
        if (mService != null) {
            mService = null;
            try {
                mContext.unbindService(mConnection);
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "Unable to unbind HidDevService", e);
            }
        }
    }

    void close() {
        Log.v(TAG, "close()");

@@ -265,16 +276,8 @@ public final class BluetoothHidDevice implements BluetoothProfile {
        }

        synchronized (mConnection) {
            if (mService != null) {
                mService = null;
                try {
                    mContext.unbindService(mConnection);
                } catch (IllegalArgumentException e) {
                    Log.e(TAG, "close: could not unbind HID Dev service: ", e);
            doUnbind();
        }
            }
        }

        mServiceListener = null;
    }

@@ -388,7 +391,9 @@ public final class BluetoothHidDevice implements BluetoothProfile {
    /**
     * Unregisters application. Active connection will be disconnected and no
     * new connections will be allowed until registered again using
     * {@link #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)}
     * {@link #registerApp
     * (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
     * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)}
     *
     * @param config {@link BluetoothHidDeviceAppConfiguration} object as obtained from {@link
     * BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice,
+10 −1
Original line number Diff line number Diff line
@@ -21,7 +21,16 @@ import android.os.Parcelable;

import java.util.Random;

/** @hide */
/**
 * Represents the app configuration for a Bluetooth HID Device application.
 *
 * The app needs a BluetoothHidDeviceAppConfiguration token to unregister
 * the Bluetooth HID Device service.
 *
 * {@see BluetoothHidDevice}
 *
 * {@hide}
 */
public final class BluetoothHidDeviceAppConfiguration implements Parcelable {
    private final long mHash;

+18 −6
Original line number Diff line number Diff line
@@ -19,7 +19,17 @@ package android.bluetooth;
import android.os.Parcel;
import android.os.Parcelable;

/** @hide */
/**
 * Represents the Quality of Service (QoS) settings for a Bluetooth HID Device
 * application.
 *
 * The BluetoothHidDevice framework will update the L2CAP QoS settings for the
 * app during registration.
 *
 * {@see BluetoothHidDevice}
 *
 * {@hide}
 */
public final class BluetoothHidDeviceAppQosSettings implements Parcelable {

    public final int serviceType;
@@ -36,8 +46,7 @@ public final class BluetoothHidDeviceAppQosSettings implements Parcelable {
    public static final int MAX = (int) 0xffffffff;

    public BluetoothHidDeviceAppQosSettings(int serviceType, int tokenRate, int tokenBucketSize,
            int peakBandwidth,
            int latency, int delayVariation) {
            int peakBandwidth, int latency, int delayVariation) {
        this.serviceType = serviceType;
        this.tokenRate = tokenRate;
        this.tokenBucketSize = tokenBucketSize;
@@ -66,10 +75,13 @@ public final class BluetoothHidDeviceAppQosSettings implements Parcelable {
                @Override
                public BluetoothHidDeviceAppQosSettings createFromParcel(Parcel in) {

                    return new BluetoothHidDeviceAppQosSettings(in.readInt(), in.readInt(),
                    return new BluetoothHidDeviceAppQosSettings(
                            in.readInt(),
                            in.readInt(),
                            in.readInt(),
                            in.readInt(),
                            in.readInt(),
                            in.readInt(), in.readInt());
                            in.readInt());
                }

                @Override
+18 −3
Original line number Diff line number Diff line
@@ -19,7 +19,18 @@ package android.bluetooth;
import android.os.Parcel;
import android.os.Parcelable;

/** @hide */
/**
 * Represents the Service Discovery Protocol (SDP) settings for a Bluetooth
 * HID Device application.
 *
 * The BluetoothHidDevice framework adds the SDP record during app
 * registration, so that the Android device can be discovered as a Bluetooth
 * HID Device.
 *
 * {@see BluetoothHidDevice}
 *
 * {@hide}
 */
public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {

    public final String name;
@@ -57,8 +68,12 @@ public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {
                @Override
                public BluetoothHidDeviceAppSdpSettings createFromParcel(Parcel in) {

                    return new BluetoothHidDeviceAppSdpSettings(in.readString(), in.readString(),
                            in.readString(), in.readByte(), in.createByteArray());
                    return new BluetoothHidDeviceAppSdpSettings(
                            in.readString(),
                            in.readString(),
                            in.readString(),
                            in.readByte(),
                            in.createByteArray());
                }

                @Override
+13 −5
Original line number Diff line number Diff line
@@ -18,16 +18,24 @@ package android.bluetooth;

import android.util.Log;

/** @hide */
/**
 * The template class that applications use to call callback functions on
 * events from the HID host. Callback functions are wrapped in this class and
 * registered to the Android system during app registration.
 *
 * {@see BluetoothHidDevice}
 *
 * {@hide}
 */
public abstract class BluetoothHidDeviceCallback {

    private static final String TAG = BluetoothHidDeviceCallback.class.getSimpleName();
    private static final String TAG = "BluetoothHidDevCallback";

    /**
     * Callback called when application registration state changes. Usually it's
     * called due to either
     * {@link BluetoothHidDevice#registerApp(String, String, String, byte, byte[],
     * BluetoothHidDeviceCallback)}
     * {@link BluetoothHidDevice#registerApp
     * (String, String, String, byte, byte[], BluetoothHidDeviceCallback)}
     * or
     * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)}
     * , but can be also unsolicited in case e.g. Bluetooth was turned off in
@@ -79,7 +87,7 @@ public abstract class BluetoothHidDeviceCallback {
    /**
     * Callback called when SET_REPORT is received from remote host. In case
     * received data are invalid, application shall respond with
     * {@link BluetoothHidDevice#reportError(BluetoothDevice)}.
     * {@link BluetoothHidDevice#reportError(BluetoothDevice, byte)}.
     *
     * @param type Report Type.
     * @param id Report Id.