云计算百科
云计算领域专业知识百科平台

Android音频学习(九)——AudioPolicyService

        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);

整体流程如下:

赞(0)
未经允许不得转载:网硕互联帮助中心 » Android音频学习(九)——AudioPolicyService
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!