基于Android 11 aosp 源码分析。
目录
AudioManager.java, 提供了注册外部策略的接口:
针对与Car, Android 将音频策略部分,通过提供外部(app 层)注入的方式,放在更加灵活的 app java层来实现。
以前的android基本为了手机设计,输出设备相对较少也不会给应用来控制,应用只是给一个stream类型,由AudioPolicy在底层根据你的stream类型偷偷地给你选一个设备,现在android要用于车机,发现这些音频设备变多了,手机上的那一套做很难满足需求,为了即保留对原来手机的逻辑支持,有可在车机上自定义更高级的策略玩法,于是想了个办法,把所有设备对应什么用途这些定义不再是直接写在AudioPolicy里面了,而是可以通过函数的方式注入进来,这样这些设备用途的定义,都可以放在更加灵活的app层面来做,并且不光是设备的usage定义,还有音量控制,音频焦点请求等这些逻辑一样,都可以先把回调注入 进来。
如此,对于手机上的场景,可以使用默认的策略,对于汽车,只需要再添加一个app,把新的策略注册进去即可覆盖替换原先的策略。 这个支持app层注册音频规则和控制回调的策略,即动态策略,它包括了 设备选择(mix规则)、音量控制(分频分区域控制音量)、音频焦点申请这三个策略。
@TestApi @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull AudioPolicy policy) {
return registerAudioPolicyStatic(policy);
}
有了这个接口,mix规则就可以放在 app 层实现,通过这个方法注入进去。当然,不是所有app都能随意注册,需要systemapp , 需要MODIFY_AUDIO_ROUTING权限
默认不注册动态策略,也就是传统的手机设备,如果在车机,只需要 加入这么一个系统app,在app层实现动态策略然后注入,底层即可适配。
注入这里的AudioPolicy.java 它和 底层AudioPolicyServer里面的AudioPolicy没什么关系,仅仅是用来包含这个动态策略的一个类而已。AudioManager.java作为java层对外提供的api,大部分时候也只是一个空壳,内部还是通过调用AudioServer.java ,而AudioServer.java再调用音频系统总功能AudioSystem.cpp 在java层的接口AudioSystem.java
AudioServer
- AudioService.java::
- public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
- boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy,
- boolean isVolumeController, IMediaProjection projection) {
- ...
- if (isFocusPolicy) {
- // 1.0 焦点控制的回调,
- ...
- mMediaFocusControl.setFocusPolicy(mPolicyCallback, mIsTestFocusPolicy);
- }
-
- if (mIsVolumeController) {
- // 2.0 音量控制的回调
- setExtVolumeController(mPolicyCallback);
- }
-
- // 3.0 mix规则
- connectMixes(){
- ....
- AudioSystem.registerPolicyMixes(mMixes, true);
- }
- }
按音量+-键,系统会触发AudioServer.java的 adjustSuggestedStreamVolume(),如果注册了外部音量控制器,就直接由外部控制器处理音量事件。在AudioServer.java中,通过notifyExternalVolumeController() 全部交给外部策略来控制,处理完即返回
app通过AudioManager.java接口请求获取焦点 requestAudioFocus(), 如果注入了外部焦点策略,就通知外部策略模块处理焦点请求。
在MediaFocusControl.java中,通过notifyExtFocusPolicyFocusRequest_syncAf()交给外部策略处理,外部处理完策略,可以通过 AudioManager.java::setFocusRequestResult()
( ->AudioServer.java::setFocusRequestResultFromExtPolicy()->MediaFocusControl.java::setFocusRequestResultFromExtPolicy() )
将结果设置回来,由AudioManager 把结果发给引用层通知app其焦点发送变化,如果是有framework强制duck的,AudioMnager在发送结果的同时还会让MediFocusControl执行duck操作,外部策略只需要处理焦点策略逻辑。
则是AudioSystem.registerPolicyMixes() 直接注册到AudioPolicy中的,用于设备选择的规则。