车机高通蓝牙电话-音频收发流程
1. 整体架构概览
手机(蓝牙耳机侧)
↓ HFP协议
车机蓝牙模块(Qualcomm)
↓ HCI/UART
高通蓝牙协议栈
↓ Audio HAL
车机音频系统
↓ DSP/Codec
扬声器/麦克风
2. 音频通道类型
2.1 SCO(Synchronous Connection-Oriented)通道
- 用途:双向语音通话
- 带宽:64kbps
- 编码:CVSD(8kHz)或 mSBC(16kHz宽频)
- 延迟:低延迟,同步传输
2.2 eSCO(Enhanced SCO)通道
- 支持重传机制
- 更好的抗干扰能力
- 支持多种编码格式
3. 完整音频收发时序
3.1 来电音频建立流程
1. 手机来电 →
2. 车机接听 →
3. 建立SCO链路 →
4. 音频路由切换 →
5. 开始双向音频流 →
6. 实时语音通信
4. 音频接收流程(手机→车机)
4.1 接收端代码流程
HeadsetClientStateMachine.java:
java
// packages/apps/Bluetooth/src/com/android/bluetooth/hfpclient/
// HeadsetClientStateMachine.java
// 处理来电音频连接
private class Connected extends State {
@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CONNECT_AUDIO:
Log.d(TAG, "开始建立音频接收通道");
// 1. 请求建立SCO连接
if (!mNativeInterface.connectAudio(mDevice.getAddress())) {
Log.e(TAG, "Native connectAudio失败");
return NOT_HANDLED;
}
// 2. 更新音频状态
mAudioState = BluetoothHeadsetClient.STATE_AUDIO_CONNECTING;
broadcastAudioStateChange();
// 3. 配置音频路由
AudioManager audioManager = (AudioManager) mContext.getSystemService(
Context.AUDIO_SERVICE);
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
Log.d(TAG, "音频接收通道建立中...");
return HANDLED;
case AUDIO_CONNECTED:
Log.d(TAG, "音频接收通道已建立");
mAudioState = BluetoothHeadsetClient.STATE_AUDIO_CONNECTED;
broadcastAudioStateChange();
// 4. 开始接收音频数据
startAudioReceiving();
return HANDLED;
}
return NOT_HANDLED;
}
}
4.2 音频HAL接收处理
cpp
// hardware/qcom/audio/hal/audio_hw.c
// SCO音频接收处理
static int sco_in_read(struct audio_stream_in* stream,
void* buffer,
size_t bytes) {
struct stream_in* in = (struct stream_in*)stream;
struct audio_device* adev = in->dev;
int ret;
ALOGV("%s: 读取SCO音频数据, 需要 %zu 字节", __func__, bytes);
// 1. 从蓝牙协议栈读取SCO数据
ret = read(adev->sco_fd, buffer, bytes);
if (ret < 0) {
ALOGE("读取SCO数据失败: %s", strerror(errno));
return ret;
}
// 2. 高通DSP处理
if (adev->sco_dsp_enabled) {
// 2.1 解码(CVSD或mSBC)
if (adev->sco_codec == CODEC_MSBC) {
decode_msbc_to_pcm(buffer, bytes, in->pcm_buffer);
} else {
decode_cvsd_to_pcm(buffer, bytes, in->pcm_buffer);
}
// 2.2 音频增强处理
process_received_audio(in->pcm_buffer,
bytes / 2, // 16-bit samples
AUDIO_DIRECTION_RX);
// 2.3 复制到输出缓冲区
memcpy(buffer, in->pcm_buffer, bytes);
}
// 3. 更新统计信息
in->frames_read += bytes / audio_stream_in_frame_size(stream);
adev->sco_rx_bytes += bytes;
ALOGV("%s: 成功读取 %d 字节", __func__, ret);
return ret;
}
4.3 高通蓝牙协议栈接收
cpp
// system/bt/btif/src/btif_hf_client.cc
// 接收SCO数据回调
static void bta_hf_client_sco_data_callback(uint16_t sco_handle,
uint8_t* data,
uint16_t len) {
ALOGV("%s: 收到SCO数据, handle: %d, 长度: %d",
__func__, sco_handle, len);
// 1. 查找对应的HFP客户端
btif_hf_client_cb_t* btif_hf = btif_hf_client_find_by_sco_handle(sco_handle);
if (btif_hf == NULL) {
ALOGE("找不到对应的HFP客户端");
return;
}
// 2. 解码音频数据
int16_t* pcm_data = decode_sco_audio(data, len, btif_hf->codec);
// 3. 发送到音频HAL
if (pcm_data != NULL) {
// 3.1 音频后处理
process_audio_rx(pcm_data, len / 2); // 除以2因为16-bit
// 3.2 写入PCM设备
write_to_pcm_device(pcm_data, len / 2,
btif_hf->pcm_out_handle);
// 3.3 更新统计
btif_hf->stats.rx_packets++;
btif_hf->stats.rx_bytes += len;
}
// 4. 检查音频质量
check_audio_quality(btif_hf);
}
5. 音频发送流程(车机→手机)
5.1 发送端代码流程
音频服务层:
java
// frameworks/base/services/core/java/com/android/server/audio/
// AudioService.java
public void startBluetoothScoForClient(IBinder cb, String callingPackage) {
synchronized (mDeviceStateLock) {
// 1. 检查权限和状态
if (!checkBluetoothScoPermission(callingPackage)) {
return;
}
// 2. 设置音频模式
setMode(AudioManager.MODE_IN_CALL, callingPackage);
// 3. 设置蓝牙SCO设备
AudioSystem.setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO,
AudioSystem.DEVICE_STATE_AVAILABLE,
"");
AudioSystem.setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
AudioSystem.DEVICE_STATE_AVAILABLE,
"");
// 4. 启动SCO音频
AudioSystem.setParameters("bt_sco=on");
// 5. 设置音频路由
setForceUse(AudioSystem.FOR_COMMUNICATION,
AudioSystem.FORCE_BT_SCO);
// 6. 开始音频采集
startAudioCaptureForSco();
Log.d(TAG, "蓝牙SCO音频发送已启动");
}
}
5.2 音频HAL发送处理
cpp
// hardware/qcom/audio/hal/audio_hw.c
// SCO音频发送处理
static int sco_out_write(struct audio_stream_out* stream,
const void* buffer,
size_t bytes) {
struct stream_out* out = (struct stream_out*)stream;
struct audio_device* adev = out->dev;
int ret;
ALOGV("%s: 写入SCO音频数据, %zu 字节", __func__, bytes);
// 1. 高通DSP前处理
if (adev->sco_dsp_enabled) {
// 1.1 车机麦克风处理
process_car_microphone_audio((int16_t*)buffer,
bytes / 2, // 16-bit samples
adev->mic_array_data);
// 1.2 音频增强
process_transmit_audio((int16_t*)buffer,
bytes / 2,
AUDIO_DIRECTION_TX);
// 1.3 编码(CVSD或mSBC)
if (adev->sco_codec == CODEC_MSBC) {
encode_pcm_to_msbc((int16_t*)buffer,
out->encoded_buffer,
bytes / 2);
ret = bytes * 2; // mSBC压缩率
} else {
encode_pcm_to_cvsd((int16_t*)buffer,
out->encoded_buffer,
bytes / 2);
ret = bytes; // CVSD基本无压缩
}
} else {
// 直接复制
memcpy(out->encoded_buffer, buffer, bytes);
ret = bytes;
}
// 2. 发送到蓝牙协议栈
ssize_t written = write(adev->sco_fd,
out->encoded_buffer,
ret);
if (written < 0) {
ALOGE("写入SCO数据失败: %s", strerror(errno));
return written;
}
// 3. 更新统计信息
out->frames_written += bytes / audio_stream_out_frame_size(stream);
adev->sco_tx_bytes += written;
ALOGV("%s: 成功写入 %zd 字节", __func__, written);
return bytes;
}
5.3 高通车机麦克风处理
cpp
// vendor/qcom/proprietary/bt/car/audio/qti_car_mic_processing.c
// 车机麦克风阵列处理
void process_car_microphone_array(int16_t** mic_inputs, // 多路麦克风输入
int num_mics, // 麦克风数量
int16_t* processed_output, // 处理后的输出
int frames) { // 音频帧数
// 1. 波束成形 - 指向驾驶员
beamform_to_driver(mic_inputs,
processed_output,
frames,
get_driver_position());
// 2. 噪声抑制 - 车机环境
suppress_car_noise(processed_output,
frames,
get_car_noise_profile());
// 3. 回声消除 (AEC)
apply_acoustic_echo_cancellation(processed_output,
frames,
get_speaker_reference());
// 4. 自动增益控制 (AGC)
adjust_gain_for_car_environment(processed_output,
frames,
get_car_speed(),
get_window_status());
// 5. 高通专有优化
apply_qti_voice_enhancement(processed_output, frames);
// 6. 限幅保护
apply_limiter(processed_output, frames, MAX_VOICE_LEVEL);
}
6. 双向音频同步管理
6.1 音频同步控制
cpp
// system/bt/bta/hf_client/bta_hf_client_audio.c
// 音频同步管理
typedef struct {
uint32_t rx_timestamp; // 接收时间戳
uint32_t tx_timestamp; // 发送时间戳
int32_t clock_offset; // 时钟偏移
uint16_t jitter_buffer; // 抖动缓冲区大小
bool synchronization_lost; // 同步是否丢失
} bta_hf_client_audio_sync_t;
// 同步音频流
static void synchronize_audio_streams(bta_hf_client_audio_sync_t* sync,
uint8_t* rx_data,
uint8_t* tx_data,
uint16_t len) {
// 1. 计算时间戳
uint32_t current_time = get_current_timestamp();
uint32_t rx_time = sync->rx_timestamp;
uint32_t tx_time = sync->tx_timestamp;
// 2. 计算时钟偏移
int32_t offset = calculate_clock_offset(rx_time, tx_time, current_time);
sync->clock_offset = apply_low_pass_filter(sync->clock_offset, offset);
// 3. 调整发送时间
if (abs(sync->clock_offset) > CLOCK_OFFSET_THRESHOLD) {
// 需要重新同步
resynchronize_audio_clocks(sync);
}
// 4. 应用抖动缓冲
apply_jitter_buffer(rx_data, len, sync->jitter_buffer);
// 5. 更新统计
update_audio_sync_statistics(sync);
ALOGV("音频同步 - 偏移: %d, 抖动: %d",
sync->clock_offset, sync->jitter_buffer);
}
7. 音频编解码处理
7.1 CVSD编解码(窄带)
cpp
// vendor/qcom/proprietary/bt/codec/cvsd_codec.c
// CVSD编码(64kbps, 8kHz)
size_t encode_cvsd(const int16_t* pcm_data, // 16-bit PCM数据
uint8_t* encoded_data, // 编码后数据
size_t pcm_samples) { // PCM采样数
CVSDEncoderState* state = get_cvsd_encoder_state();
size_t encoded_bits = 0;
for (size_t i = 0; i < pcm_samples; i++) {
// 1. 预测当前采样值
int32_t predicted = predict_next_sample(state);
// 2. 计算误差
int32_t error = pcm_data[i] - predicted;
// 3. 量化为1bit
uint8_t bit = (error >= 0) ? 1 : 0;
// 4. 存储到输出
encoded_data[encoded_bits / 8] |= (bit << (7 - (encoded_bits % 8)));
encoded_bits++;
// 5. 更新状态
update_encoder_state(state, bit);
}
return (encoded_bits + 7) / 8; // 转换为字节数
}
// CVSD解码
size_t decode_cvsd(const uint8_t* encoded_data, // 编码数据
int16_t* pcm_data, // 解码后PCM
size_t encoded_bytes) { // 编码数据字节数
CVSDDecoderState* state = get_cvsd_decoder_state();
size_t decoded_samples = 0;
for (size_t byte_idx = 0; byte_idx < encoded_bytes; byte_idx++) {
for (int bit_idx = 7; bit_idx >= 0; bit_idx--) {
// 1. 读取1bit
uint8_t bit = (encoded_data[byte_idx] >> bit_idx) & 0x01;
// 2. 预测采样值
int32_t predicted = predict_next_sample(state);
// 3. 重构采样值
int16_t sample = reconstruct_sample(state, predicted, bit);
// 4. 存储PCM数据
pcm_data[decoded_samples++] = sample;
// 5. 更新状态
update_decoder_state(state, bit);
if (decoded_samples >= MAX_PCM_SAMPLES) {
break;
}
}
}
return decoded_samples;
}
7.2 mSBC编解码(宽频)
cpp
// vendor/qcom/proprietary/bt/codec/msbc_codec.c
// mSBC编码(64kbps, 16kHz)
size_t encode_msbc(const int16_t* pcm_data, // 16-bit PCM, 16kHz
uint8_t* encoded_data, // 编码后数据
size_t pcm_samples) { // 必须是120个采样(7.5ms)
MSBCEncoderState* encoder = get_msbc_encoder();
// 1. 分帧处理(每帧120个采样)
size_t num_frames = pcm_samples / MSBC_FRAME_SAMPLES;
size_t encoded_size = 0;
for (size_t frame = 0; frame < num_frames; frame++) {
const int16_t* frame_data = &pcm_data[frame * MSBC_FRAME_SAMPLES];
// 2. SBC编码
sbc_encode_frame(encoder, frame_data,
&encoded_data[encoded_size]);
// 3. 添加同步字和CRC
add_msbc_sync_word(&encoded_data[encoded_size]);
add_msbc_crc(&encoded_data[encoded_size]);
encoded_size += MSBC_FRAME_SIZE; // 每个mSBC帧57字节
}
return encoded_size;
}
8. 音频质量监控
8.1 实时质量监控
cpp
// vendor/qcom/proprietary/bt/audio/qti_audio_quality_monitor.c
// 音频质量监控结构
typedef struct {
// 网络指标
uint32_t packet_loss_rate; // 丢包率 (0-100%)
uint32_t jitter_buffer_size; // 抖动缓冲区大小 (ms)
uint32_t round_trip_time; // 往返延迟 (ms)
int32_t signal_strength; // 信号强度 (dBm)
// 音频指标
uint32_t audio_bitrate; // 音频码率 (kbps)
uint32_t audio_volume; // 音频音量 (0-100)
uint32_t noise_level; // 噪声水平 (dB)
uint32_t echo_level; // 回声水平 (dB)
// 系统指标
uint32_t cpu_usage; // CPU使用率 (%)
uint32_t memory_usage; // 内存使用率 (%)
uint32_t buffer_underruns; // 缓冲区欠载次数
} audio_quality_metrics_t;
// 监控线程
static void* audio_quality_monitor_thread(void* arg) {
audio_quality_metrics_t metrics = {0};
while (g_monitor_running) {
// 1. 收集各项指标
collect_network_metrics(&metrics);
collect_audio_metrics(&metrics);
collect_system_metrics(&metrics);
// 2. 计算综合质量分数
int quality_score = calculate_quality_score(&metrics);
// 3. 动态调整参数
if (quality_score < QUALITY_THRESHOLD_LOW) {
adjust_for_poor_quality(&metrics);
} else if (quality_score > QUALITY_THRESHOLD_HIGH) {
adjust_for_good_quality(&metrics);
}
// 4. 记录日志
log_quality_metrics(&metrics, quality_score);
// 5. 发送质量报告
if (need_to_report_quality(&metrics)) {
send_quality_report(&metrics);
}
usleep(MONITOR_INTERVAL_US);
}
return NULL;
}
9. 车机特定优化
9.1 多音区音频管理
cpp
// vendor/qcom/proprietary/bt/car/qti_car_audio_zone.c
// 车机音频分区
typedef enum {
ZONE_DRIVER = 0, // 驾驶位
ZONE_PASSENGER, // 副驾驶位
ZONE_REAR_LEFT, // 左后座
ZONE_REAR_RIGHT, // 右后座
ZONE_REAR_CENTER, // 后座中央
ZONE_ALL, // 全车
MAX_AUDIO_ZONES
} car_audio_zone_t;
// 配置驾驶位音频
void configure_driver_zone_audio(car_audio_config_t* config) {
// 1. 麦克风配置
config->mic_selection = MIC_STEERING_WHEEL; // 优先使用方向盘麦克风
config->mic_beamforming = BEAMFORM_DIRECTION_DRIVER;
config->mic_noise_cancellation = NOISE_CANCEL_LEVEL_HIGH;
// 2. 扬声器配置
config->speaker_zone = SPEAKER_ZONE_DRIVER;
config->speaker_volume = 80; // 0-100
config->speaker_balance = 0; // 居中
// 3. 音频处理
config->echo_cancellation = true;
config->noise_suppression = true;
config->automatic_gain_control = true;
config->wind_noise_reduction = true;
// 4. 高通专有优化
config->qti_voice_enhancement = true;
config->qti_audio_optimization = AUDIO_OPTIMIZATION_CAR_MODE;
// 5. 保存配置
save_car_audio_config(ZONE_DRIVER, config);
}
9.2 方向盘麦克风处理
cpp
// 方向盘麦克风专用处理
void process_steering_wheel_mic(int16_t* audio_data,
int samples,
steering_wheel_sensors_t* sensors) {
// 1. 方向盘振动补偿
compensate_steering_vibration(audio_data, samples,
sensors->vibration_level,
sensors->vibration_frequency);
// 2. 按钮点击噪声检测和消除
remove_button_click_noise(audio_data, samples,
sensors->button_press_mask);
// 3. 安全气囊区域静音
mute_airbag_zone(audio_data, samples,
sensors->airbag_deployment_risk);
// 4. 方向盘角度补偿
apply_steering_angle_compensation(audio_data, samples,
sensors->steering_angle);
// 5. 驾驶员头部位置跟踪
adjust_for_driver_head_position(audio_data, samples,
sensors->driver_head_position);
// 6. 高通车机语音优化
apply_qti_car_voice_optimization(audio_data, samples);
}
10. 错误处理和恢复
10.1 音频错误处理
java
// packages/apps/Bluetooth/src/com/android/bluetooth/hfpclient/
// HeadsetClientStateMachine.java
private void handleAudioError(int errorCode) {
Log.e(TAG, "音频错误: " + getAudioErrorString(errorCode));
switch (errorCode) {
case ERROR_AUDIO_CONNECTION_FAILED:
// 音频连接失败
handleAudioConnectionFailure();
break;
case ERROR_AUDIO_DISCONNECTED:
// 音频意外断开
handleAudioDisconnection();
break;
case ERROR_AUDIO_QUALITY_POOR:
// 音频质量差
handlePoorAudioQuality();
break;
case ERROR_AUDIO_SYNC_LOST:
// 音频同步丢失
handleAudioSyncLoss();
break;
case ERROR_AUDIO_CODEC_MISMATCH:
// 编解码器不匹配
handleCodecMismatch();
break;
default:
Log.w(TAG, "未知音频错误");
disconnectAudio();
break;
}
}
// 音频质量差处理
private void handlePoorAudioQuality() {
// 1. 降低音频质量以提高稳定性
if (mCurrentCodec == CODEC_MSBC) {
Log.w(TAG, "音频质量差,从mSBC切换到CVSD");
switchToCvsdCodec();
}
// 2. 增加抖动缓冲区
increaseJitterBuffer();
// 3. 启用前向纠错
enableForwardErrorCorrection();
// 4. 降低发送音量
reduceTransmitVolume();
// 5. 通知用户
notifyAudioQualityWarning();
}
11. 调试和日志
11.1 音频调试命令
bash
# 查看音频设备状态
adb shell tinymix
# 查看PCM设备信息
adb shell tinypcminfo -D 0
# 查看音频路由
adb shell cat /proc/asound/cards
# 查看蓝牙音频状态
adb logcat -s AudioFlinger,AudioHardware,bt_audio
# 查看SCO连接状态
adb shell cat /sys/kernel/debug/bluetooth/hci0/sco
# 实时音频监控
adb shell dumpsys audio | grep -i bluetooth
11.2 性能测试脚本
bash
#!/bin/bash
# test_bt_audio.sh
echo "=== 蓝牙音频性能测试 ==="
# 1. 测试音频延迟
echo "1. 测试音频延迟..."
adb shell "echo '测试音频延迟' > /sys/kernel/debug/bluetooth/test_audio_latency"
# 2. 测试音频质量
echo "2. 测试音频质量..."
adb shell "tinymix 'Audio Quality Test' 1"
sleep 2
adb shell "tinymix 'Audio Quality Test' 0"
# 3. 查看统计信息
echo "3. 音频统计信息:"
adb shell "cat /sys/kernel/debug/bluetooth/audio_stats"
# 4. 压力测试
echo "4. 开始压力测试..."
for i in {1..100}; do
echo "测试循环 $i/100"
adb shell "tinymix 'Audio Test' $i"
sleep 0.1
done
echo "测试完成"
这个完整的音频收发流程涵盖了从蓝牙协议栈到音频HAL,再到DSP处理和车机特定优化的所有环节。