AudioPolicyService(APS)是 Android 音频系统的 策略控制中枢,负责管理音频路由、设备切换、音量策略、策略冲突解决等关键决策。它与 AudioFlinger(负责音频数据处理)协同工作,共同构成 Android 音频框架的核心。
1. 核心职责
音频路由决策 | 根据场景(通话/音乐/通知)和当前设备状态(耳机/扬声器/蓝牙)动态选择最佳输出路径 |
设备状态管理 | 监听设备连接/断开(如耳机拔出),触发路由切换和策略更新 |
音量策略控制 | 管理不同流类型(音乐/通话/警报)的独立音量曲线,支持设备差异化配置 |
策略冲突仲裁 | 解决多应用同时请求音频焦点时的优先级冲突(如通话打断音乐) |
音频焦点管理 | 通过 AudioFocus 机制协调应用对音频资源的抢占式使用 |
2 核心工作流程
2.1设备状态变化处理(以耳机插入为例):
(1)UEventObserver 监听内核事件 → 检测耳机插入
(2)调用 setDeviceConnectionState() 更新设备状态
(3)AudioPolicyManager 重新计算路由策略
(4)通知 AudioFlinger 重新打开输出流
(5)广播 ACTION_HEADSET_PLUG 通知应用
2.2音频播放路由决策:
// 示例:选择输出设备的核心逻辑 (简化版)
audio_io_handle_t AudioPolicyManager::getOutputForAttr() {
// 1. 根据音频属性(usage, content type)确定流类型
audio_stream_type_t stream = _streamForAttributes(attr);
// 2. 检查当前设备可用性(扬声器/耳机/蓝牙等)
DeviceVector availableDevices = getAvailableOutputDevices();
// 3. 应用路由策略规则(优先级:蓝牙 > 有线耳机 > 扬声器)
DeviceDescriptor device = _findDeviceForStrategy(
getStrategyForStream(stream),
availableDevices
);
// 4. 创建/复用对应的输出流
return openOutputWithProfile(device, profile);
}
3. 关键组件交互
4.策略配置机制
-
配置文件:audio_policy_configuration.xml(路径:/vendor/etc/)
-
关键配置项:
-
设备定义(扬声器/耳机/蓝牙A2DP)
-
音量曲线(不同设备的最大/最小音量映射)
-
策略规则(如"媒体播放时插入耳机自动切换")
-
-
动态策略:通过 AudioManager.setPreferredDevice() 允许应用临时覆盖路由
5. 典型场景分析
场景:来电打断音乐播放
(1)电话应用请求 AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
(2)APS 暂停音乐播放流(发送 AUDIOFOCUS_LOSS_TRANSIENT)
(3)切换音频路由到听筒/蓝牙耳机
(4)通话结束恢复音乐播放(自动路由回原设备)
6. 性能与延迟优化
-
异步命令处理:通过 AudioCommandThread 队列处理路由切换,避免阻塞主线程
-
设备热切换延迟:蓝牙设备切换通常需 200-500ms(受限于 A2DP 协议栈)
-
缓存机制:常用输出流保持打开状态减少延迟
7.厂商定制要点
-
HAL 扩展:实现 audio_policy HAL 接口支持特殊硬件
-
策略覆盖:重写 AudioPolicyManager::getDeviceForStrategy() 修改路由逻辑
-
调试工具:
adb shell dumpsys media.audio_policy # 获取完整策略状态
8.挑战与演进
-
多设备协同:Android 13 引入 AudioDeviceBroker 统一管理 LE Audio/多设备输出
-
低延迟路由:AAudio API 支持绕过策略直接访问低延迟路径
-
车载系统扩展:支持多区独立音频策略(Android Automotive)
9.AudioPolicyService初始化流程
首先在main_audioserver.cpp的main函数中调用instantiate()方法,搜了下并没有实现该方法,推断从父类中继承,继承了BinderService的instantiate()。
int main(int argc __unused, char **argv)
{
…
sp<IServiceManager> sm = defaultServiceManager();
…
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
…
}
最终返回一个media.audio_policy的服务。
static const char *getServiceName() ANDROID_API { return "media.audio_policy"; }
在AudioPolicyService的构造函数中,仅做了初始化工作
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService(),
mAudioPolicyManager(NULL),
mAudioPolicyClient(NULL),
mPhoneState(AUDIO_MODE_INVALID),
mCaptureStateNotifier(false) {
}
由于sm是sp<IServiceManager>强引用类型的指针,所以在第一次调用AudioPolicyService模块时,会调用AudioPolicyService::onFirstRef()
void AudioPolicyService::onFirstRef()
{
{
Mutex::Autolock _l(mLock);
// start audio commands thread
mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
// start output activity command thread
mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
mAudioPolicyClient = new AudioPolicyClient(this);
mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
}
// load audio processing modules
sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects();
sp<UidPolicy> uidPolicy = new UidPolicy(this);
sp<SensorPrivacyPolicy> sensorPrivacyPolicy = new SensorPrivacyPolicy(this);
{
Mutex::Autolock _l(mLock);
mAudioPolicyEffects = audioPolicyEffects;
mUidPolicy = uidPolicy;
mSensorPrivacyPolicy = sensorPrivacyPolicy;
}
uidPolicy->registerSelf();
sensorPrivacyPolicy->registerSelf();
}
在onFirstRef中,创建了mAudioCommandThread,mOutputCommandThread,mAudioPolicyClient,以及mAudioPolicyManager。
createAudioPolicyManager方法中传入了上一步创建的mAudioPolicyClient。
创建AudioPolicyManager对象时,首先会加载配置文件,位置在开发版的vendor/etc/audio_policy_configuration.xml或/system/etc/audio_policy_configuration.xml,代码中可在/frameworks/av/services/audiopolicy/config中查找,具体在下一篇中分析。
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
: AudioPolicyManager(clientInterface, false /*forTesting*/)
{
loadConfig();
}
接下来调用apm的initialize(),根据从配置文件中解析出的HwMoudle的Name加载对应的音频硬件模块,最终调用到af的loadHwModule(),后面文章会继续分析。我们可以看到AudioPolicyService初始化时会调用到af的方法,所以AudioFlinger初始化在前,AudioPolicyService在后。
audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == 0) {
ALOGW("%s: could not get AudioFlinger", __func__);
return AUDIO_MODULE_HANDLE_NONE;
}
return af->loadHwModule(name);
整体流程如下:
评论前必须登录!
注册