蓝牙电话顾名思义就是使用蓝牙技术实现电话拨打相关功能,当前市面上一般运用到蓝牙音箱、蓝牙手环和蓝牙车载等设备上,由于车载蓝牙涉及到的知识点更全面,所以主要以车载为第一视角讲解蓝牙电话相关的内容。
蓝牙电话总体上涉及到蓝牙的HFP和PBAP这两种协议,本篇分享先介绍HFP,PBAP留待下一篇文章继续。
Hands-Free Profile简称HFP,协议规定了免提设备控制电话相关操作,这里的免提设备指的就是相关的蓝牙设备(如车载蓝牙、蓝牙音箱等)。详细描述请参考协议文档HFP_v1.7.1.pdf。
先来大致了解下蓝牙电话在安卓系统中的架构,然后逐层分析各部分的作用:
蓝牙电话应用:下发用户指令、接收蓝牙服务上报的数据,并将数据处理后显示在相关界面上。由于是以车载蓝牙为分析视角,所以使用的相关协议都是Client端的,手机蓝牙作为Server端。
蓝牙API:安卓系统对外提供的API,这里主要用到BluetoothHeadsetClient.java、BluetoothPbapClient.java。
由于安卓源码中关于蓝牙协议的client部分或相关接口都被@hide给隐藏掉了,这样 android.jar 满足不了安卓源码framework层开发人员的需求。
解决方法:安卓源码全编后会在路径:out\target\common\obj\JAVA_LIBRARIES\framework_intermediates下生成包含所有接口的classes.jar文件,该jar包可以替换android.jar使用。
蓝牙服务:实现所有的上层服务以及与蓝牙协议栈bluedroid交互,这里主要依赖于hfpclient和pbapclient这两个模块。
JNI:实现JAVA层调用C语言模块,路径:packages\apps\Bluetooth\jni。
蓝牙协议栈:也被称为蓝牙核心协议栈Host部分(android4.2开始主要采用博通开源蓝牙协议栈bluedroid),大部分的蓝牙协议的实现都是在这一模块内完成的,通过HCI和底层蓝牙芯片进行消息交互。
蓝牙芯片:蓝牙核心协议栈Controller部分,完成蓝牙协议里偏底层的相关定义,主要由各蓝牙芯片厂商开发实现功能。
以上就是蓝牙电话架构各部分在安卓系统中具体的作用,接下来会从HFP的连接、通话、AT命令集、语音音频这四个方面做进一步分析。因为HFP的连接和通话都和上层应用有关联,所以先对这两部分作出分析。
连接
手机音频profile的连接具体分为AG和HF这两个角色,
AG:Audio Gate,音频网关,音频设备输入输出设备——手机
HF:Hands Free,免提设备,作为音频网关远程输入输出机制,并可以提供控制功能——车载蓝牙
手机音频的连接AG和HF侧都可以发起,连接过程中的消息交互及流程大体相同。本篇文章没有特殊声明,第一视角都是车载蓝牙(HF侧)作为分析起点。上层应用调用API触发HFP协议的连接,则底层各模块相互合作直到连接成功上报HFP的连接状态,应用层监测到连接状态后则整个过程完成,详细流程见如下时序图:
从上面完整的HFP连接时序图可以看出蓝牙电话应用的操作只需要调用HFP协议的连接API后监听系统中对应的广播就行,大部分工作都在bluedroid内完成,各层分工明确高效。
连接过程中唯一需要注意的是蓝牙服务层只有在在Service Level Connection连接完成后(对应于相关AT命令依次交互完成)才会对外广播连接状态改变到Connected的广播。
这样在操作连接HFP协议失败时,我们就可以从以下六个方面分析原因:
1、 应用层是否正确调用连接的相关API
2、 应用层是否正确设置监听广播
3、 当前蓝牙的ACL链路是否建立成功
4、 SDP服务搜索HFP协议是否正常完成
5、 RFCOMM是否连接成功
6、 AT命令是否依次交互完成
AT命令依次交互的顺序为:
BRSF -> BAC(AG、HF都支持codec协商) -> CIND=? -> CIND? -> CMER -> CHLD=?(AG、HF都支持三方通话) -> ……
下图为HFP连接在HCI层的完整流程(PS:RFCOMM连接前应该会有l2cap链路的连接,由于这份log中前面已经连接成功,所以截图中没有RFCOMM的l2cap链路连接)
HFP连接的流程大体就是上面这些要点,后面三部分的内容我们在接下来的文章中再做分析。