开始前,扯点题外话:本人不爱写网络文档,从2009年开始做蓝牙到现在(这13年都是在本地PC 写文档,自己写自己看,或分享给公司同仁,但从没想过上传网络),还是从去年(2021)年开始挑点文档上传到网络(受刺激了...),希望对大家有用;
本文将详细介绍Android Bluetooth HID Host从初始化、连接及最后接收Report Data 并如何写入Android 节点"/dev/uhid"的全过程;
本文继续以问答形式展开;
问题点1:关于原生HID的类名;
关于原生HID, 其在Android 9是一个分界线;
在Android 8(O),
Framework层的HID Device 类是:BluetoothInputHost;
Framework层的HID Host类是: BluetoothInputDevice;
以上类命名和我们理解是反向的;
从Android 9 开始,HID 的命名符合常规:
Framework层的HID Device 类是: BluetoothHidDevice;
Framework层的HID Host类是:BluetoothHidHost;
其分别对应的Service
HidDeviceService.java 和HidHostService.java
其分别对应的JNI层接口是:
com_android_bluetooth_hid_device.cpp 和com_android_bluetooth_hid_host.cpp
其分别对应的BlueDroid层接口是:
btif_hd.cc 和btif_hh.cc
以下Tracing 基于Android 9开始,重点Tracing HID Host部分;
问题点2:关于HID Host的初始化流程;
-->Profile 的初始化属于Server APK 中的HidHostService中的start 方法,在此方法里调用JNI函数initializeNative;
-->通过JNI 函数,回归到com_android_bluetooth_hid_host.cpp中的:
执行到com_android_bluetooth_hid_host.cpp中的函数initializeNative;
-->在com_android_bluetooth_hid_host.cpp中的函数initializeNative,在此函数里通过HAL层接口,获取到了BlueDroid 中定义的HID Host 结构体bthh_interface_t接口;随后开始调用init函数;
-->因函数指针结构体bthh_interface_t的实作在btif_hh.cc (system\bt\btif\src),
所以执行init将对应到到btif_hh.cc中的init函数指针的实作函数
static bt_status_t init(bthh_callbacks_t* callbacks)
通过此实作函数,并把com_android_bluetooth_hid_host.cpp中的callback
“sBluetoothHidCallbacks”注册到了BlueDroid层;
在此函数中开始执行BlueDroid层的profile service初始化
“btif_enable_service(BTA_HID_SERVICE_ID);”
这里注册HID Host的Service 使用的宏定义是BTA_HID_SERVICE_ID,
而HID Device对应的是BTA_HIDD_SERVICE_ID
-->最终执行到HID_HostInit;
问题点3:HID Host的SDP 注册在哪;
在Android 原生BT 中,定义HID UUID 是:
#define UUID_SERVCLASS_HUMAN_INTERFACE 0X1124 /* HID profile */
从当前checking,以及结合SDP注册相关API,我们没有在HID Host中发现其SDP注册的实现;就Android作为手机时,基本都是主动搜索并进行连接,而作为HID Device 的几乎都是无界面设备,基本是等待被搜索并连接;---所以原生Android无HID Host注册的行为目前只能基于场景猜想;
延伸问题点:Andorid Bluetooth HID Device 的SDP 注册 ;
目前我们找到HID Device 添加Service 的API 是:HID_DevAddRecord,在
hidd_api.h/hidd_api.cc中
问题点4:原生BT HID Host如何问询remote SDP并解析;
SDP API定义在sdp_api.h中
-->HID Host中执行SDP 问询的API是HID_HostGetSDPRecord,API 内部执行
SDP_InitDiscoveryDb 和 SDP_ServiceSearchRequest;
-->通过API SDP_ServiceSearchRequest,注册SDP callback API hidh_search_callback
Note :关于查询HID Device 的SDP,重点是找到SDP中附带注册的report descriptor(报告描述符),基于HID Spec,其Attribute ID 是0x0206;
-->找到SDP callback中的报告描述符相关,
#define ATTR_ID_HID_DESCRIPTOR_LIST 0x0206;
有一个现象需留意: 在APIhidh_search_callback中,能看到其记录了SDP中的report descriptor ” p_nvi->dscp_info.dsc_list”, 但并没有在hidh_search_callback中看到对SDP中包含的报告描述符的解析,;----具体原因请参考“问题点6”