Android-Adding Bluetooth Profile

From Texas Instruments Embedded Processors Wiki

Jump to: navigation, search
Translate this page to   

This wiki highlights on - "How to add bluetooth profile(HID) support into android framework". This can be taken as a reference to add more profiles for bluetooth or other software stack under android framework.

Contents

Android Bluetooth Framewrok

BT Stack.jpg

Bluetooth profiles supported by android

Android's Bluetooth stack uses BlueZ for:

BlueZ Website: http://wiki.bluez.org/ Documentation: mydroid\external\bluez\utils\doc

Bluez is GPL licensed, so the Android framework interacts with userspace bluez code through D-BUS IPC to avoid proprietary code.

D-BUS website: http://www.freedesktop.org/wiki/IntroductionToDBus

Android Bluetooth Source

<android-src>/external/bluez
<android-src>/kernel/drivers/bluetooth
<android-src>/kernel/net/bluetooth
<android-src>/frameworks/base/core/jni/android_bluetooth_*.cpp
<android-src>/frameworks/base/core/java/android/bluetooth/*.java
<android-src>/frameworks/bases/services/java/com/android/server (system_server)
<android-src>/packages/apps/Phone/src/com/android/phone (Phone App)
<android-src>/package/apps/Settings/src/com/android/settings/bluetooth/ (Settings App)

Bluetooth event flow in Android Source Tree

500px-Bluetooth Source Flow Android.jpg
Above diagram explains a sequence of bluetooth event flow with respect to android source tree

e.g. Bluetooth input device - Exposed API is available at <android-src>/external/bluetooth/bluez/doc/input-api.txt

Input hierarchy
===============
Service     org.bluez
Interface   org.bluez.Input
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
Methods     void Connect()
            Connect to the input device.

        	void Disconnect()
            Disconnect from the input device.

	        dict GetProperties()
            Returns all properties for the interface. See the
            properties section for available properties.


Signals     PropertyChanged(string name, variant value)

            This signal indicates a changed value of the given
            property.

Properties  boolean Connected [readonly]

            Indicates if the device is connected.
frameworks/base/core/jni/Android.mk
frameworks/base/jcore/jni/AndroidRuntime.cpp
frameworks/base/core/jni/android_server_BluetoothEventLoop.cpp
frameworks/base/core/jni/android_server_BluetoothHidService.cpp
frameworks/base/core/java/android/server/BluetoothEventLoop.java
frameworks/base/core/java/android/server/BluetoothHidService.java
frameworks/base/services/java/com/android/server/SystemServer.java
Application:
packages/apps/Phone/src/com/android/phone
package/apps/Settings/src/com/android/settings/bluetooth/

Service : (android.bluetooth)
frameworks/base/core/java/android/bluetooth/BluetoothClass.java
frameworks/base/core/java/android/bluetooth/BluetoothUuid.java
frameworks/base/core/java/android/bluetooth/BluetoothHid.java

AIDL:
frameworks/base/core/java/android/bluetooth/IBluetoothHid.aidl

Adding a bluetooth HID profile

http://processors.wiki.ti.com/index.php/File:Bluetooth-HID-support-Android.zip

Create JNI interface


static bool initNative(JNIEnv* env, jobject object) {
	/* open dbus connection */
}

static void cleanupNative(JNIEnv* env, jobject object) {
	 /* close dbus connection */
}

static jobjectArray getInputPropertiesNative(JNIEnv *env, jobject object,
                                            jstring path) {
	/* talk to bluez with interface org.bluez.Input and method :GetProperties */
}

static jboolean connectInputNative(JNIEnv *env, jobject object, jstring path) {
	/* talk to bluez with interface org.bluez.Input and method :Connect */
}

static jboolean disconnectInputNative(JNIEnv *env, jobject object,
                                     jstring path) {
	/* talk to bluez with interface org.bluez.Input and method :Disconnect */
}

DBusHandlerResult hid_event_filter(DBusMessage *msg, JNIEnv *env) {
	/* talk to bluez with interface org.bluez.Input and signal :PropertyChanged */
}

static JNINativeMethod sMethods[] = {
    {"initNative", "()Z", (void *)initNative},
    {"cleanupNative", "()V", (void *)cleanupNative},

    /* Bluez audio 4.40 API */
    {"connectInputNative", "(Ljava/lang/String;)Z", (void *)connectInputNative},
    {"disconnectInputNative", "(Ljava/lang/String;)Z", (void *)disconnectInputNative},
    {"getInputPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
                                    (void *)getInputPropertiesNative},                                                       
};

int register_android_server_BluetoothHidService(JNIEnv *env) {
	/* register HID service and methods mentioned above */
}

/* Open :<android-src>/frameworks/base/core/jni/android_server_BluetoothEventLoop.cpp */
/* 1. add entry to fucntion static "setUpEventLoop" */
static jboolean setUpEventLoop(native_data_t *nat) {
.....
.....
	dbus_bus_add_match(nat->conn,
       "type='signal',interface='org.bluez.Input'",
       &err);
        if (dbus_error_is_set(&err)) {
            LOG_AND_FREE_DBUS_ERROR(&err);
            return JNI_FALSE;
        }
..
..
}

/* 2. add entry to function "tearDownEventLoop" */
static void tearDownEventLoop(native_data_t *nat) {
.....
....
 dbus_bus_remove_match(nat->conn,
       "type='signal',interface='org.bluez.Input'",
        &err);
	    if (dbus_error_is_set(&err)) {
            LOG_AND_FREE_DBUS_ERROR(&err);
        }

....
}

/* 3. delcare extern for hid_event_filter : Implemented in android_server_BluetoothHidService.cpp */
extern DBusHandlerResult hid_event_filter(DBusMessage *msg, JNIEnv *env);

/* call "hid_event_filter(msg, env);" in function :event_filter
static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
                                      void *data) {
.....
.....
hid_event_filter(msg, env);
ret = a2dp_event_filter(msg, env);
}
/* open frameworks/base/core/jni/Android.mk, add android_server_BluetoothHidService.cpp for build  */
LOCAL_SRC_FILES += android_server_BluetoothHidService.cpp
/* open : frameworks/base/core/jni/AndroidRuntime.cpp and add HID service registration */
extern int register_android_server_BluetoothHidService(JNIEnv* env);
/* in function static const RegJNIRec add HID entry */
static const RegJNIRec gRegJNI[] = {
....
....
REG_JNI(register_android_server_BluetoothHidService),
....
....
}

Create framework service for Bluetooth HID

/* create file :frameworks/base/java/android/server/BluetoothHidService.java */
/* implement wrapper APIs for all methods present in JNI interface. For more info on code kindly refer attached patch */
/* open file : <android-src>/frameworks/base/services/java/com/android/server/SystemServer.java */
import android.server.BluetoothHidService;
public void run() {
....
....
	BluetoothService bluetooth = null;
    BluetoothA2dpService bluetoothA2dp = null;
    /* HID port - start */
    BluetoothHidService bluetoothHid = null;
    /* HID port - end */
....
....
	bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
    ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,
                                  bluetoothA2dp);
    /* HID port - start */
    if (SystemProperties.TARGET_OMAP4) {
    	bluetoothHid = new BluetoothHidService(context, bluetooth);
        ServiceManager.addService(BluetoothHidService.BLUETOOTH_HID_SERVICE,
        							bluetoothHid);
    }
    /* HID port - end */
....
....
}
/* open file :frameworks/base/core/java/android/server/BluetoothEventLoop.java */
private boolean onAgentAuthorize(String objectPath, String deviceUuid){
....
....
	if (mBluetoothService.isEnabled() &&
	..
	..
	}
    /* HID port - start */
    if (mBluetoothService.isEnabled() &&
          (BluetoothUuid.isInputHID(uuid)) && SystemProperties.TARGET_OMAP4) {
           authorized = true;
           Log.i(TAG, "Allowing incoming HID connection from " + address);
    /* HID port - end */
	}
	else {
	    Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
    }
....
....
}

Create Application Bluetooth HID service & Application moification to add bluetooth HID

http://processors.wiki.ti.com/index.php/Android-Adding_SystemService

/* create file : frameworks/base/core/java/android/bluetooth/BluetoothHid.java */
define BluetoothHID class with following methods:
public final class BluetoothHid { 
....
....
public BluetoothHid(Context c){
	/* Create a BluetoothHid proxy object for interacting with the local Bluetooth HID service */
	IBinder b = ServiceManager.getService(BluetoothHidService.BLUETOOTH_HID_SERVICE);
	mService = IBluetoothHid.Stub.asInterface(b); 
}
public boolean connectInput(BluetoothDevice device) {
	/* Initiate a connection to an HID input device */
	mService.connectInput(device);
}
public boolean disconnectInput(BluetoothDevice device) {
	/* Initiate disconnect from an HID input device.  */
	mService.disconnectInput(device);
}
public int getInputState(BluetoothDevice device) {
	/*  Get the state of an HID input device */
	 mService.getInputState(device);
}
....
/* Add more custom methods */
....
}
/* open file : frameworks/base/core/java/android/bluetooth/BluetoothUuid.java */
public final class BluetoothUuid {
....
....
public static final ParcelUuid HID =
            ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb");
....
/* public static final ParcelUuid[] RESERVED_UUIDS = {
        AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
        ObexObjectPush};*/
change to 
public static final ParcelUuid[] RESERVED_UUIDS = {
        AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
        ObexObjectPush,HID};
...
/* HID port - start */
    public static boolean isInputHID(ParcelUuid uuid) {
        return uuid.equals(HID);
    }
/* HID port - end */
...
}
/* open file : frameworks/base/core/java/android/bluetooth/BluetoothClass.java */
/* HID port - start */
/** @hide */
	public static final int PROFILE_HID = 3;
/* HID port - end */
/* create file :frameworks/base/core/java/android/bluetooth/IBluetoothHid.aidl */
/* refer patch for more details */

Refer attached patch for more details

References

http://processors.wiki.ti.com/index.php/Android-Adding_SystemService
http://www.slideshare.net/erinyueh/android-bluetooth-introduction
https://sites.google.com/a/android.com/opensource/projects/bluetooth-faq
CategoryBeagleboard

E2e.jpg For technical support on OMAP please post your questions on The OMAP Forum. Please post only comments about the article Android-Adding Bluetooth Profile here.
Hyperlink blue.png Links
ARM Microcontroller MCU ARM Processor Digital Media Processor Digital Signal Processing Microcontroller MCU Multi Core Processor
Ultra Low Power DSP 8 bit Microcontroller MCU 16 bit Microcontroller MCU 32 bit Microcontroller MCU

Leave a Comment
Personal tools
Namespaces
Variants
Actions
Navigation
Print/export
Toolbox