HFP(Hands-Free Profile)是蓝牙技术中用于实现免提通话的核心协议,主要支持在蓝牙设备(如耳机、车载系统)与手机之间建立语音和控制通道,使设备能够作为手机的远程扬声器和麦克风,并提供通话控制功能(如接听/挂断、音量调节等)。
角色
1. 角色定义
角色 | 设备示例 | 核心功能 |
---|---|---|
AG | 手机、平板、电脑等音源设备 | 负责管理通话、音频数据路由及控制响应。 |
HF | 车载系统、蓝牙耳机、音箱等 | 作为用户操作入口,发送控制指令并播放音频。 |
2. 核心职责对比
2.1 AG(Audio Gateway)
- 通话管理
- 接听/挂断电话、拒接来电、切换通话(多方通话)。
- 生成并发送通话状态(如振铃、通话中、空闲)。
- 音频路由
- 将音频流(如通话语音)通过SCO/eSCO链路传输到HF设备。
- 切换音频路径(如从手机扬声器切换到蓝牙耳机)。
- 响应控制指令
- 处理HF发送的命令(如拨号、重拨、音量调节)。
- 信息推送
- 发送来电号码、联系人姓名(CLIP)、信号强度、电池状态等。
2.2 HF(Hands-Free)
- 用户交互
- 通过物理按键或语音指令触发操作(如接听、挂断)。
- 显示通话状态、来电信息(依赖AG推送的数据)。
- 音频播放
- 接收并播放来自AG的通话语音(通过SCO链路)。
- 支持麦克风输入,采集用户语音并发送给AG。
- 控制指令发起
- 向AG发送命令(如拨号、静音、音量调节)。
3. 角色交互流程示例(以接听电话为例)
- 来电触发
- AG检测到来电,通过
RING
通知HF。 - HF显示来电信息(需支持
+CLIP
功能)。
- AG检测到来电,通过
- 用户操作
- 用户按下HF的接听键,HF发送
AT+ATA
指令给AG。
- 用户按下HF的接听键,HF发送
- 通话建立
- AG接听电话,通过
SCO链路
传输语音数据到HF。 - HF播放对方语音,并通过麦克风采集本端语音回传AG。
- AG接听电话,通过
- 挂断控制
- 用户按下HF挂断键,HF发送
AT+CHUP
指令,AG终止通话。
- 用户按下HF挂断键,HF发送
4. 关键协议支持
不同角色需实现以下HFP子功能(取决于协议版本):
功能 | AG职责 | HF职责 |
---|---|---|
基本通话控制 | 响应AT+ATA 、AT+CHUP 等指令 | 发送接听、挂断等控制指令 |
音频切换 | 管理SCO链路启停及编解码协商 | 支持PCM接口或编解码器(如CVSD) |
来电显示(CLIP) | 发送+CLIP 消息包含来电号码 | 解析并显示来电信息 |
电池状态同步 | 发送+CIND 指示电量 | 显示电量或触发低电量提醒 |
语音拨号 | 执行拨号操作 | 发送ATD 指令(支持语音识别) |
5. 开发注意事项
-
角色初始化
- 设备需在蓝牙配对阶段声明自身角色(AG或HF),例如:
// 蓝牙协议栈配置(以BlueZ为例) hfp_profile_set_role(HFP_ROLE_AG); // 设为音频网关
- 双角色设备:部分设备(如智能手表)可能同时支持AG和HF角色,需动态切换。
- 设备需在蓝牙配对阶段声明自身角色(AG或HF),例如:
-
SCO链路管理
- AG负责启动SCO链路,需协商编码格式(CVSD、mSBC等)和参数(如eSCO重传窗口)。
- HF需实现PCM接口或编解码器以处理音频流。
-
功能兼容性
- 部分低端HF设备仅支持基础功能(如接听/挂断),需处理功能缺失场景(如隐藏电量显示)。
-
错误处理
- AG需响应HF的无效指令(如发送
ERROR
或+CME ERROR
代码)。
- AG需响应HF的无效指令(如发送
6. 典型问题与解决
-
通话无声音
- 检查SCO链路是否建立成功(如
HCI_SCO_Connection_Complete
事件)。 - 确认音频路由已切换到HF设备(AG侧调用
AudioManager.setBluetoothSCOOn(true)
)。
- 检查SCO链路是否建立成功(如
-
来电信息不显示
- 确认AG支持
+CLIP
功能且已启用(需运营商支持)。 - HF需解析
RING
消息中的附加号码信息。
- 确认AG支持
-
语音指令失效
- 检查HF是否支持
+BVRA
(语音识别激活)指令。 - 确保AG侧语音识别服务(如Google Voice)已启用。
- 检查HF是否支持
总结
HFP通过AG和HF角色的明确分工,实现了蓝牙设备间的通话控制与语音传输。开发中需注意:
- 角色配置:设备需正确声明角色(AG/HF),避免指令无法响应。
- 协议版本适配:根据设备支持的功能集(如HFP 1.6+的宽频语音)调整交互逻辑。
- 音频链路管理:确保SCO/eSCO链路参数兼容,避免通话质量下降。
2. 主要应用场景
- 车载系统:通过车载蓝牙实现免提通话。
- 蓝牙耳机/耳麦:无线接听电话。
- 智能手表/手环:显示来电信息并控制通话。
- 智能家居设备:通过语音助手接打电话。
3. HFP 的核心功能
3.1 电话控制
- 接听/挂断电话:通过蓝牙设备物理按键或语音指令控制。
- 拒绝来电:发送拒绝指令(如忙时自动拒接)。
- 多方通话管理:支持切换或合并通话。
- 重拨/静音:通过设备控制手机功能。
3.2 音频传输
- 语音通道:传输双向音频(下行:手机到设备;上行:设备到手机)。
- 音频编解码:支持CVSD(默认)、mSBC(宽带语音)等编码格式。
3.3 状态同步
- 来电显示:同步联系人姓名、号码到蓝牙设备。
- 信号强度/电量显示:部分设备支持显示手机信号和耳机电量。
- 通话状态同步:显示通话时长、通话中等状态。
3.4 附加功能
- 语音助手激活:通过蓝牙设备唤醒手机语音助手(如Siri、Google Assistant)。
- 号码拨号:部分设备支持通过语音指令拨号。
4. HFP 协议版本演变
版本 | 新增功能 |
---|---|
HFP 1.0 | 基础通话控制、音频传输。 |
HFP 1.5 | 支持增强型呼叫控制(如保持通话)。 |
HFP 1.6+ | 支持宽带语音(mSBC编解码器),提升音质。 |
HFP 1.7+ | 优化多设备连接、支持更高效的状态同步。 |
5. HFP 的工作流程
5.1 设备配对与连接
- 配对:蓝牙设备与手机交换安全密钥。
- 服务发现:手机识别设备支持的HFP功能。
- 建立连接:
- 控制通道(RFCOMM):传输AT命令(如接听、挂断)。
- 音频通道(SCO/eSCO):传输语音数据。
5.2 通话流程示例
- 来电时:手机通过控制通道发送
RING
通知。 - 接听:蓝牙设备发送
ATA
命令,手机接通并切换音频到蓝牙设备。 - 挂断:设备发送
ATH
命令或手机主动结束通话。 - 音频切换:通话结束后,音频切回手机听筒或扬声器。
6. 技术细节
6.1 音频编码与传输
- CVSD(Continuous Variable Slope Delta Modulation):
- 默认编码,8 kHz采样率,适用于窄带语音(300-3400 Hz)。
- 抗干扰强,但音质一般。
- mSBC(Modified Subband Coding):
- 支持宽带语音(50-7000 Hz),16 kHz采样率,音质更清晰。
- 需设备双方支持HFP 1.6+。
6.2 关键协议层
- RFCOMM:模拟串口,传输AT命令(控制通话)。
- SCO(Synchronous Connection-Oriented):同步音频链路,低延迟但易受干扰。
- eSCO(Enhanced SCO):支持重传,提高稳定性。
6.3 AT 命令集
HFP 使用AT命令控制通话,例如:
AT+CLCC
:查询当前通话列表。AT+CHUP
:挂断电话。AT+VGS
:调节通话音量。
7. HFP 与其他蓝牙协议的协同
- 与A2DP(音频传输):HFP负责通话,A2DP负责音乐播放,两者可共存但音频通道需切换。
- 与PBAP(电话簿访问):同步联系人至车载系统。
- 与MAP(消息访问):同步短信/即时消息(部分车载系统支持)。
8.安卓策略
在蓝牙电话应用中,音频链路(SCO/eSCO)建立后,系统需要通过多层次的协调机制来管理音频焦点、避免多音源冲突,并通过底层硬件接口控制语音数据流。以下是详细的技术实现逻辑:
1. 音频焦点管理与多音源控制
1.1 音频焦点机制
-
申请音频焦点
蓝牙电话在收到AUDIO_STATE_CHANGED
广播(如AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED
)后,通过AudioManager.requestAudioFocus()
申请音频焦点。AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); int result = am.requestAudioFocus( focusChangeListener, AudioManager.STREAM_VOICE_CALL, // 流类型为通话 AudioManager.AUDIOFOCUS_GAIN // 独占焦点 );
- 流类型优先级:
STREAM_VOICE_CALL
的优先级高于STREAM_MUSIC
,通话会暂停音乐播放(通过OnAudioFocusChangeListener
回调通知音乐APP暂停)。
- 流类型优先级:
-
音频焦点抢占规则
- 高优先级流(如通话)可抢占低优先级流(如音乐)。
- 若音乐APP未正确处理焦点丢失(如未暂停),系统可能强制静音低优先级流。
1.2 通话模式切换
- 设置音频模式
蓝牙电话需调用AudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION)
,通知Audio HAL(硬件抽象层)切换到通话模式:am.setMode(AudioManager.MODE_IN_COMMUNICATION); // 启用通话音频路径
- 底层行为:
- Audio HAL会关闭非通话相关的音频输出(如媒体播放)。
- 蓝牙芯片的PCM接口被路由到通话通道,取代扬声器或耳机输出。
- 底层行为:
2. 静音功能的实现
2.1 静音本地麦克风
- 静音操作
通过AudioManager.setMicrophoneMute(true)
静音本地麦克风:am.setMicrophoneMute(true); // 本地Mic静音,对方无法听到本端语音
- 底层行为:
- 若蓝牙耳机作为输入设备,系统会静音蓝牙的PCM输入通道(而非手机内置Mic)。
- 语音数据在基带层直接被丢弃,不会传输到对方设备。
- 底层行为:
2.2 静音与硬件协作
- 蓝牙芯片控制
部分蓝牙芯片支持硬件级静音(如通过HCI指令直接关闭麦克风输入),避免数据进入传输链路:// 示例:发送HCI指令静音HF设备(基带层) hci_send_cmd(HCI_Write_SCO_PCM_Parameters, 0x01); // 0x01表示静音
3. 语音数据传输与开发难点
3.1 语音数据路径
-
传输链路
- 上行(本端→对方):
手机Mic → Audio HAL → 蓝牙AG基带 → eSCO链路 → 蓝牙HF基带 → 对方设备Audio输出。 - 下行(对方→本端):
对方Mic → 蓝牙HF基带 → eSCO链路 → 蓝牙AG基带 → Audio HAL → 手机扬声器/蓝牙耳机。
- 上行(本端→对方):
-
数据隔离性
语音数据在基带层和PCM接口直接传输,绕过Android AudioFlinger,上层应用无法直接捕获。
3.2 获取通话语音的方法
尽管语音数据在底层传输,仍可通过以下方式获取:
-
AudioRecord捕获
- 在通话模式下,尝试通过
AudioRecord
读取原始PCM数据:AudioRecord record = new AudioRecord( MediaRecorder.AudioSource.VOICE_COMMUNICATION, // 通话音源 sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize );
- 限制:需要
CAPTURE_AUDIO_OUTPUT
权限(仅系统级APP可用)。
- 在通话模式下,尝试通过
-
蓝牙芯片调试接口
- 通过厂商私有协议(如Qualcomm的QMI、Broadcom的HCI扩展指令)从基带层dump语音数据。
- 示例(伪代码):
// 启用基带语音数据回环(仅调试模式) hci_send_cmd(HCI_Enable_Debug_SCO_Loopback, 0x01);
-
修改Audio HAL
- 在Audio HAL层插入自定义模块,复制PCM数据到上层(需系统源码权限)。
4. 开发注意事项
-
音频焦点释放
- 通话结束后需释放焦点并恢复音频模式:
am.abandonAudioFocus(focusChangeListener); // 释放焦点 am.setMode(AudioManager.MODE_NORMAL); // 恢复默认模式
- 通话结束后需释放焦点并恢复音频模式:
-
兼容性处理
- 不同厂商可能对音频焦点和SCO链路有定制行为(如某些设备静音后仍发送噪声),需实测验证。
-
低延迟优化
- 调整eSCO参数(如重传窗口、编码方式)以降低通话延迟:
// 配置eSCO链路参数(Air Coding格式为CVSD,HV3分组) esco_params = BTM_ESCO_SETTINGS(BTM_ESCO_LINK_TYPE_CVSD, 0x000A, 0x0080);
- 调整eSCO参数(如重传窗口、编码方式)以降低通话延迟:
总结
蓝牙电话通过音频焦点抢占、通话模式切换和硬件静音控制实现多音源管理,语音数据在底层基带和PCM接口传输以避免冲突。开发者可通过以下方式扩展功能:
- 利用系统级权限捕获语音(需定制ROM或权限)。
- 与蓝牙芯片厂商合作,通过调试接口获取数据。
- 修改Audio HAL层插入自定义处理逻辑(适用于深度定制系统)。