Android 设备作为 蓝牙音箱使用,需要android支持a2dp sink ,hfp等功能。 Android 作为手机平台,默认不支持作为slave端的a2dp sink 与hfp功能,需要需要配置对应。
aosp/package/app/Bluetooth/res/values/config.xml
将profile_supported_hfpclient 设置为true,同时profile_supported_hs_hfp设置为false即可。
重新编译打包进rom中,刷机后,可正常与master端设备连接。打接电话功能都正常,但是遇到通话无声音问题。
经过好长时间的分析,整理一下android 蓝牙相关的部分记录。
Android 系统蓝牙分为几个部分:
1.aosp/package/app/Bluetooth: 蓝牙协议栈功能实现部分,主要是在package中Bluetooth应用完成,由上层功能通过jni直接与android Bluetooth 协议栈通信。
2.aosp/systemj/bt :Android Bluetooth 协议栈接口部分,这部分作为系统外设支持,独立出来并未放到framework当中。
3.aosp/framework/av/service: android系统音视频模块服务实现部分,如系统音频核心模块audioflinger 与audiopolicy就在这个部分中。
通过以上三个部分加上蓝牙芯片厂商的具体协议栈实现库,便可完成android 设备整个蓝牙通信流程。
android Bluetooth 协议栈中实现的功能较多,接下来只结合设备端通话免提功能(HFP)做下流程分析.。
bluetooth/hfpclient/connserv/HfpClientConnection.java
bluetooth/hfpclient/connserv/HfpClientConnectionService.java
bluetooth/hfpclient/HeadsetClientService.java
bluetooth/hfpclient/HeadsetClientStateMachine.java
以上hfp应用部分
HfpClientConnectionService: 负责通话连接的管理服务,根据接收到的广播状态,创建slave与master设备对应关系,有内部hashmap mDeviceBlocks 保存。并根据对应广播创建呼入连接,呼出连接等等。
HfpClientConnection :则表示所建立的单个连接,该连接可根据用户具体的操作来响应 呼入电话,挂断电话,接听电话等等功能。
HeadsetClientService:提供Bluetooth Headset 设备客户端HFP功能的服务;初始化native接口相关函数,以便与协议栈进行通信;管理master设备与slave设备对应的状态机。
HeadsetClientStateMachine:slave设备状态机,根据设备连接以及语音通道切换做出相应的处理。状态机切换流程如下:
HeadsetClientStateMachine
以上就是hfp应用部分大致处理流程。应用部分流程相对清晰,出问题概率比较小。在实际调试中,hfp协议与语音是分为两部分连接。一部分是hfp 业务连接,另一部分对应的音频sco连接。当都连接正常时,才能即建立通话成功通话连接,同时语音传输也可以正常收发。
HeadsetClientStateMachine
在设置音频打开对应audio设备时,jni 底层回调设置音频msbc状态,设置slave端音频对应采样率和音量等相关参数。此时audioManager通过调用AudioSystem 最终调用到AudioFlinger
setParameters函数,针对hfp 则对应参数为hfp_enalbe true 或false的键值对。
在调试过程中,若发现音频数据不正确,可以在Threads.cpp中针对write audio buffer 和read audio buffer 函数中,使用audio dump工具 保存原始音频流数据做进一步分析对比。