NOTICE: The Processors Wiki will End-of-Life on January 15, 2021. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.
Android-Adding Bluetooth Profile
Content is no longer maintained and is being kept for reference only!
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[edit]
Bluetooth profiles supported by android[edit]
Android's Bluetooth stack uses BlueZ for:
- GAP profile: Generic Access protocol
- SDP profile : Service discovery protocol
- Headset and Handsfree (v1.5) profiles are implemented in the Android framework and are both tightly coupled with the Phone App. These profiles are also SIG qualified.
- RFCOMM profile: Cable replacement protocol,and is a SIG-qualified Bluetooth 2.0 host stack.
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[edit]
- Bluez 3.38 (user space and kernel)
<android-src>/external/bluez <android-src>/kernel/drivers/bluetooth <android-src>/kernel/net/bluetooth
- Android App framework (java & c++)
<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 UI application
<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[edit]
Above diagram explains a sequence of bluetooth event flow with respect to android source tree
- BlueZ
- BlueZ provides support for the core Bluetooth layers and protocols
- Android BlueZ is software stack implenation which will get/send bluetooth controls and data to/from bluetooth h/w using kenrel (bluez) modules.
- BlueZ also expose a interface for android framework which enable door to access bluetooth functionalities.
- Documenataion of exposed interface can be found at <android-src>/external/bluetooth/bluez/doc
- Android framework communicates with bluez using D-Bus protocol.Interface to use for diffenent types of bluetooth porfile is documented at <android-src>/external/bluetooth/bluez/doc
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.
- Framework Layer
- Bluetooth functionality in a framewrok is divided in two parts
- Bluetooth JNI Service : This component talks to bluez using D-Bus interface
- Bluetooth functionality in a framewrok is divided in two parts
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
- Bluetooth Service Layer : This component provides interface to application to communicate with bluez using component#1.
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 Layer
- Application : Component that creates user interface
- Service : Component talks to android framewrok using AIDL to get/send bluetooth controls and data
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[edit]
- Note : For complete code reference guide; kindly take reference of attached patch.
http://processors.wiki.ti.com/index.php/File:Bluetooth-HID-support-Android.zip
Create JNI interface[edit]
- Create File:<android-src>/frameworks/base/core/jni/android_server_BluetoothHidService.cpp
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 */ }
- Add HID support to eventloop :
/* 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); }
- Register HID service and add build support
/* 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[edit]
- Create bluetooth HID service
/* 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 */
- register bluetooth HID service with system server
/* 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 */ .... .... }
- Add authorization check at BluetoothEventLoop.java
/* 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[edit]
- Kindly refer user guide for creating custom service at
http://processors.wiki.ti.com/index.php/Android-Adding_SystemService
- Create Blueetooth HID custom application service
/* 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 */ .... }
- Create Uuid for bluetooth HID profile
/* 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 */ ... }
- Create HID profile ID
/* 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 AIDL file and add in build file
/* create file :frameworks/base/core/java/android/bluetooth/IBluetoothHid.aidl */ /* refer patch for more details */
- Change application
Refer attached patch for more details
References[edit]
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