前言

我们解析完成car_audio_configuration.xml后,接下来就是动态路由策略的注册,以及多音区的焦点管理,本篇先看下动态路由策略。

正文

CarAudioService启动后,我们先回顾下setupDynamicRoutingLocked这个函数

    private void setupDynamicRoutingLocked() {final AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);builder.setLooper(Looper.getMainLooper());// 加载xml的loadCarAudioZonesLocked();for (int i = 0; i < mCarAudioZones.size(); i++) {CarAudioZone zone = mCarAudioZones.valueAt(i);// Ensure HAL gets our initial value//同步当前音量zone.synchronizeCurrentGainIndex();Log.v(CarLog.TAG_AUDIO, "Processed audio zone: " + zone);}//动态路由策略设置CarAudioDynamicRouting.setupAudioDynamicRouting(builder, mCarAudioZones);// Attach the {@link AudioPolicyVolumeCallback}// 注册volume调节的callbackbuilder.setAudioPolicyVolumeCallback(mAudioPolicyVolumeCallback);if (sUseCarAudioFocus) {// Configure our AudioPolicy to handle focus events.// This gives us the ability to decide which audio focus requests to accept and bypasses// the framework ducking logic.// 初始化CarZonesAudioFocusmFocusHandler = new CarZonesAudioFocus(mAudioManager,mContext.getPackageManager(),mCarAudioZones,mCarAudioSettings, ENABLE_DELAYED_AUDIO_FOCUS);builder.setAudioPolicyFocusListener(mFocusHandler);builder.setIsAudioFocusPolicy(true);}mAudioPolicy = builder.build();if (sUseCarAudioFocus) {// Connect the AudioPolicy and the focus listener// 将audiopolicy传递给carAudioFocusZonemFocusHandler.setOwningPolicy(this, mAudioPolicy);}// 动态注册路由策略int r = mAudioManager.registerAudioPolicy(mAudioPolicy);if (r != AudioManager.SUCCESS) {throw new RuntimeException("registerAudioPolicy failed " + r);}// 设置 occupan zone infosetupOccupantZoneInfo();}

我们在Android R- CarAudioService之car_audio_configuration.xml解析中主要说了loadCarAudioZonesLocked过程,今天继续看下setupAudioDynamicRouting和registerAudioPolicy的过程,先看下时序图

好多for循环,一点点来看,先看下setupAudioDynamicRouting,两个参数,一个AudioPolicy的Builder,一个carAudioZones,逻辑不是很复杂,先遍历carAudioZones再遍历tVolumeGroups

    static void setupAudioDynamicRouting(AudioPolicy.Builder builder,SparseArray<CarAudioZone> carAudioZones) {// 先遍历carAudioZonesfor (int i = 0; i < carAudioZones.size(); i++) {CarAudioZone zone = carAudioZones.valueAt(i);// 在遍历carAudioZone的VolumeGroupsfor (CarVolumeGroup group : zone.getVolumeGroups()) {// 设置每个group的策略setupAudioDynamicRoutingForGroup(group, builder);}}}

我们在解析car_audio_configuration.xml的时候,知道有多个zone,每个zone有有多个group。每个group下有多个device,每个device下又有多个context,这个函数就是遍历每个group下的这些device和context内容。

    private static void setupAudioDynamicRoutingForGroup(CarVolumeGroup group,AudioPolicy.Builder builder) {// Note that one can not register audio mix for same bus more than once.// 遍历当前group下的addressfor (String address : group.getAddresses()) {boolean hasContext = false;// 根据group下的address 拿到对应的CarAudioDeviceInfoCarAudioDeviceInfo info = group.getCarAudioDeviceInfoForAddress(address);// 将CarAudioDeviceInfo的信息赋值给到AudioFormatAudioFormat mixFormat = new AudioFormat.Builder().setSampleRate(info.getSampleRate()).setEncoding(info.getEncodingFormat()).setChannelMask(info.getChannelCount()).build();AudioMixingRule.Builder mixingRuleBuilder = new AudioMixingRule.Builder();// 遍历address下的contextfor (int carAudioContext : group.getContextsForAddress(address)) {hasContext = true;// 每个carAudioContext都会对应多个AudioAttribute的usage,根据carAudioContext得到AudioAttributes usage的数组int[] usages = CarAudioContext.getUsagesForContext(carAudioContext);// 遍历AudioAttributes的usagesfor (int usage : usages) {// 构建attributesAudioAttributes attributes = buildAttributesWithUsage(usage);mixingRuleBuilder.addRule(attributes,AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);}if (Log.isLoggable(CarLog.TAG_AUDIO, Log.DEBUG)) {Log.d(CarLog.TAG_AUDIO, String.format("Address: %s AudioContext: %s sampleRate: %d channels: %d usages: %s",address, carAudioContext, info.getSampleRate(), info.getChannelCount(),Arrays.toString(usages)));}}if (hasContext) {// It's a valid case that an audio output address is defined in// audio_policy_configuration and no context is assigned to it.// In such case, do not build a policy mix with zero rules.//mixingRuleBuilder 赋值给AudioMix 并且构建AudioMix AudioMix audioMix = new AudioMix.Builder(mixingRuleBuilder.build()).setFormat(mixFormat).setDevice(info.getAudioDeviceInfo()).setRouteFlags(AudioMix.ROUTE_FLAG_RENDER).build();// 将AudioMix add 到 AudioPolicy中builder.addMix(audioMix);}}}

这个函数就是动态路由的核心了,解析每个group下的device信息以及device下的context信息,context真正对应的是AudioAttributes的usage数组(一个context对应一个usage数组),目前这个context除了关联AudioAttributes的usage之外,还有一点权限的check,在未发现,谷歌如此设计的寓意何为。这样就等于一个device对应多个usage数组。将一个device和多个usage数组组成一个audioMix 。也就是一个音频数据通路。当我们使用同一通路上这些AudioAttributes的usage进行播放时,声音都选择同一个AudioPolicy的策略上了。如下总结了Android AOSP代码中 bus与AudioAttributes的tree目录



下一篇分析registerAudioPolicy的过程。

Android R- CarAudioService之registerAudioPolicy动态注册(一)相关推荐

  1. 【Android NDK 开发】JNI 动态注册 ( 动态注册流程 | JNI_OnLoad 方法 | JNINativeMethod 结构体 | GetEnv | RegisterNatives )

    文章目录 I . 动态注册流程 ( 总结 ) II . JNI_OnLoad 方法 III . 被注册的本地 C/C++ 方法参数 IV . JNINativeMethod 结构体 ( 核心重点 ) ...

  2. android studio登录注销,Android Studio开发基础之动态注册与注销BroadcastReceiver

    1.New→Other→BroadcastReceiver package com.example.lhb.startservice; import android.content.Broadcast ...

  3. android中的广播机制(动态注册)

    1.activity_case1.xml <?xml version="1.0" encoding="utf-8"?> <androidx.c ...

  4. Android Studio开发基础之动态注册与注销BroadcastReceiver

    1.New→Other→BroadcastReceiver package com.example.lhb.startservice;import android.content.BroadcastR ...

  5. android 注册动态广播 注销_Android学习笔记(十一)BroadcastReceiver动态注册、注销示例...

    在上一篇博文中简单介绍了一下BroadcastReceiver的相关知识点,本篇举一个在代码中动态的注册.注销BroadcastReceiver的栗子. 1.首先创建一个MyReceiver并继承Br ...

  6. Android R system_ext动态扩展分区

    Android Q lunch device刷R system.img后,发现其多了个system_ext分区. 列表如下: TPro:/ # ls -l total 65 dr-xr-xr-x 37 ...

  7. 【Android 高性能音频】Oboe 音频流打开后 耳机 / 音箱 插拔事件处理 ( 动态注册广播接收者监听耳机插拔事件 | 重新打开 Oboe 音频流 )

    文章目录 一.动态注册广播接收者监听耳机插拔事件 二.jni 层的 Oboe 播放器代码 ( 重新打开 Oboe 音频流 ) 三.相关资料 基于 [Android 高性能音频]Oboe 开发流程 ( ...

  8. android的动态注册,Android应用开发之BroadcastReceiver(广播)的静态注册和动态注册 --Android开发...

    本文将带你了解Android应用开发之BroadcastReceiver(广播)的静态注册和动态注册 --Android开发,希望本文对大家学Android有所帮助 BroadcastReceiver ...

  9. Android 第十九课 大喇叭--广播机制----动态注册监听网络变化与静态注册实现开机启动

    为了便于进行 系统级别的消息通知,Android引入了一套广播消息机制. 1.广播机制简介: 因为Android中的每个应用程序都可以对自己感兴趣的广播尽心注册,这样程序只会接收自己所关心的广播内容, ...

最新文章

  1. cfile清空文件内容_电脑C盘文件夹哪些可以删除?教你如何快速清理,旧电脑还能用3年...
  2. php 验证 e mail,PHP 表单验证 - 验证 E-mail 和 URL
  3. UrlRewrite(URL重写)--ASP.NET中的实现
  4. docker 配置nginx镜像出现 403 Forbidden的问题
  5. 2017.10.25 打鼹鼠 思考记录
  6. 有多少人欠网贷,往后的日子你打算怎么过?
  7. java super实例_Java 的 super 学习的一个实例
  8. 【0702作业】输出九九乘法表
  9. 信号与线性系统分析(吴大正,郭宝龙)(信号的分类)
  10. CodeMatic动软自动生成Nhibernate
  11. Python入门:数据结构之字典(dict)(2)
  12. 2018百度之星资格赛- 1006 三原色
  13. 2022年3月15日黑马第三天
  14. 二十、JVM命令行监控工具
  15. 优化OpenSearch的搜索结果
  16. era翻译_era是什么意思_era的翻译_音标_读音_用法_例句_爱词霸在线词典
  17. Jmeter压测输出可观报告--用表格察看结果(view results in table)输出excel格式
  18. 不安抗辩权有哪些规定
  19. unity---Mesh网格编程(四)
  20. Gimbal Lock

热门文章

  1. 语言的二义性——编译原理
  2. Ubuntu系统如何搜索要安装的软件包
  3. MM们必败潮物。。。。大眼睛的小秘密哦```````
  4. 版本管理·玩转git(团队合作)
  5. 用python画卡通图_需要用Python和OpenCV制作一张卡通漫画版的图片
  6. [深入研究4G/5G/6G专题-40]: URLLC-11-《3GPP URLLC相关协议、规范、技术原理深度解读》-5-5G Qos原理与架构: 切片、PDU会话、QosFlow、5QI、DRB
  7. 思科交换机路由器 连接配置步骤
  8. chrome浏览器的性能测试--本文引用自 百度百科http://baike.baidu.com/view/1835504.htm
  9. 项目管理需要建立团队文化
  10. window、linux、mac 文件路径禁止字符, 路径长度【全网总结】