3. Android音频基础

在车载音频工程中,Android 音频框架是连接应用层与硬件编解码器(Codec)的桥梁。理解 AudioTrack、AudioRecord、AudioFlinger、AudioPolicy 以及音频流与音频设备之间的关系,是后续进行 HAL 定制、多音区管理、音效路由和低延迟优化的前提。本节从数据流向出发,梳理这些核心组件各自的职责与协作方式。

一、核心组件与数据流向

Android 音频系统可以粗略分为四层:应用层、框架服务层、HAL 层和内核/硬件层。应用通过 AudioTrack 播放音频、通过 AudioRecord 采集音频;这两个 Java API 最终都会通过 JNI 进入 native 层,与 AudioFlinger 交互。AudioFlinger 是音频系统的“混音与调度中心”,负责创建播放线程、混音多路音频流、管理输出设备;而 AudioPolicyService 则是“策略决策中心”,决定某条音频流应该走哪个设备、音量如何映射、何时切换路由。

可以用一句话概括:AudioPolicy 决定“往哪走”,AudioFlinger 负责“怎么混、怎么送”,AudioTrack/AudioRecord 是应用侧的出入口。

应用层(App / Framework API) AudioTrack(播放) AudioRecord(采集) MediaPlayer / AudioEffect 框架服务层(Native Services) AudioFlinger 混音 · 重采样 · 线程调度 管理 PlaybackThread / RecordThread AudioPolicyService 路由决策 · 音量策略 · 设备选择 AudioPolicyManager HAL 层(Audio HAL) audio_hw_device_t audio_stream_out / in 车载多音区 / DSP 路由 内核 / 硬件层 ALSA / TinyALSA Codec / I2S / TDM 功放 / 扬声器 / 麦克风 策略 状态 数据流 ↓ 控制流 ↕

二、AudioTrack 与 AudioRecord:应用侧出入口

AudioTrack 用于播放 PCM 数据,支持两种模式:STATIC(一次性写入短音频,适合提示音)和 STREAM(持续写入,适合音乐、导航播报)。在车载场景中,导航播报、TTS、媒体音乐通常都走 STREAM 模式。创建 AudioTrack 时需要指定音频属性(AudioAttributes)、格式(采样率、声道、位深)和缓冲区大小。

// 典型 AudioTrack 创建(播放导航播报)
AudioAttributes attrs = new AudioAttributes.Builder()
    .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
    .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
    .build();

AudioFormat format = new AudioFormat.Builder()
    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    .setSampleRate(48000)
    .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
    .build();

int bufSize = AudioTrack.getMinBufferSize(48000,
    AudioFormat.CHANNEL_OUT_MONO,
    AudioFormat.ENCODING_PCM_16BIT);

AudioTrack track = new AudioTrack.Builder()
    .setAudioAttributes(attrs)
    .setAudioFormat(format)
    .setBufferSizeInBytes(bufSize * 2)
    .setTransferMode(AudioTrack.MODE_STREAM)
    .build();
track.play();
track.write(pcmData, 0, pcmData.length);

AudioRecord 则用于采集,例如车载语音助手、免提通话、车内麦克风阵列。它同样需要指定音频源(MediaRecorder.AudioSource),如 VOICE_RECOGNITION、MIC、CAMCORDER 等。采集到的 PCM 数据可以送入语音识别引擎或回声消除模块。

三、AudioFlinger:混音与调度中心

AudioFlinger 位于 frameworks/av/services/audioflinger/,是 native 层的核心服务。它主要做三件事:

  • 创建和管理线程:每个输出设备对应一个 PlaybackThread(MixerThread / DirectOutputThread / OffloadThread),每个输入设备对应一个 RecordThread。
  • 混音:将多个 AudioTrack 的 PCM 数据按音量、格式混合成一路输出。车载中常见的前排导航+后排媒体同时播放,就依赖 MixerThread 的多轨混音能力。
  • 重采样与格式转换:当应用采样率与硬件采样率不一致时,AudioFlinger 会调用 AudioResampler 进行转换。

关键理解:AudioFlinger 不决定“走哪个设备”,它只负责把数据混好并送到 AudioPolicy 指定的输出流上。设备选择、路由切换由 AudioPolicyService 完成。

四、AudioPolicy:路由与策略决策

AudioPolicyService 是 Android 音频的“交通指挥”。它根据音频流的 usage、content type、当前设备连接状态(如蓝牙、USB、耳机插入)以及车载音区配置,决定:

  • 这条流应该输出到哪个设备(内置扬声器、蓝牙 A2DP、USB Audio、车载功放)?
  • 音量组如何映射?不同音区(主驾、副驾、后排)的音量是否独立?
  • 当设备热插拔时,是否需要暂停、切换或重新路由?
  • 输入设备如何选择?麦克风阵列还是蓝牙麦克风?

在车载项目中,AudioPolicy 的配置文件通常位于 /vendor/etc/audio_policy_configuration.xml,其中定义了 audioPolicyConfiguration、modules、mixPorts、devicePorts 和 routes。HAL 工程师经常需要修改这个文件来适配多音区、多声道和外部功放。

五、音频流与音频设备的关系

Android 用 AudioAttributes 描述“这是什么声音”,用 AudioDeviceInfo 描述“声音从哪出/从哪进”。音频流(stream)是逻辑概念,音频设备(device)是物理概念,AudioPolicy 负责把逻辑流映射到物理设备。

概念 典型取值/示例 作用
Usage MEDIA / NAVIGATION / VOICE_COMMUNICATION 决定路由优先级和音量策略
Content Type MUSIC / SPEECH / SONIFICATION 影响音效处理和音量曲线
Stream Type(旧) STREAM_MUSIC / STREAM_VOICE_CALL 兼容旧 API,逐步被 Attributes 替代
Device Type DEVICE_OUT_SPEAKER / BUS / BLUETOOTH_A2DP 标识物理输出/输入设备
Audio Port mixPort / devicePort Policy 配置中的路由端点

六、车载场景案例:导航播报与媒体音乐并存

假设主驾正在用媒体音乐,同时导航发起播报。系统处理流程如下:

  1. 导航 App 创建 AudioTrack,Usage 为 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE。
  2. AudioPolicyManager 根据 usage 和当前设备状态,决定导航流走主音区扬声器,并可能触发媒体音乐“闪避”(ducking)。
  3. AudioFlinger 的 MixerThread 将导航 PCM 与媒体 PCM 按策略混音,导航音量优先。
  4. 混音后的数据通过 audio_stream_out->write() 写入 HAL。
  5. HAL 将 PCM 送到 DSP/功放,最终由扬声器输出。

调试提示:如果导航播报时媒体没有闪避,优先检查 AudioPolicy 的 ducking 配置和 AudioAttributes 的 usage 是否正确;如果播报走错音区,检查 audio_policy_configuration.xml 中的 route 和 devicePort 映射。

七、常见误区与复盘

  • 误区一:AudioFlinger 决定设备。实际上 AudioFlinger 只负责混音和线程管理,设备选择由 AudioPolicy 完成。
  • 误区二:AudioTrack 缓冲区越大越好。缓冲区过大会增加延迟,车载导航播报要求低延迟,通常取 getMinBufferSize() 的 2 倍左右。
  • 误区三:采样率不匹配会自动处理。AudioFlinger 会重采样,但重采样会引入额外延迟和音质损失,HAL 层应尽量让应用与硬件采样率一致。
  • 误区四:AudioRecord 采集不需要权限。Android 6.0 以后需要 RECORD_AUDIO 运行时权限,车载系统还需注意隐私合规。

掌握 AudioTrack、AudioRecord、AudioFlinger、AudioPolicy 以及音频流与音频设备之间的协作关系,是后续进行 Audio HAL 定制、多音区路由、低延迟优化和车载音效调试的基础。在排查音频问题时,建议按照“应用属性 → Policy 路由 → Flinger 混音 → HAL 输出 → 硬件”的顺序逐层定位,避免盲目修改配置。