Android R- CarAudioService之registerAudioPolicy动态注册(一)
前言
我们解析完成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动态注册(一)相关推荐
- 【Android NDK 开发】JNI 动态注册 ( 动态注册流程 | JNI_OnLoad 方法 | JNINativeMethod 结构体 | GetEnv | RegisterNatives )
文章目录 I . 动态注册流程 ( 总结 ) II . JNI_OnLoad 方法 III . 被注册的本地 C/C++ 方法参数 IV . JNINativeMethod 结构体 ( 核心重点 ) ...
- android studio登录注销,Android Studio开发基础之动态注册与注销BroadcastReceiver
1.New→Other→BroadcastReceiver package com.example.lhb.startservice; import android.content.Broadcast ...
- android中的广播机制(动态注册)
1.activity_case1.xml <?xml version="1.0" encoding="utf-8"?> <androidx.c ...
- Android Studio开发基础之动态注册与注销BroadcastReceiver
1.New→Other→BroadcastReceiver package com.example.lhb.startservice;import android.content.BroadcastR ...
- android 注册动态广播 注销_Android学习笔记(十一)BroadcastReceiver动态注册、注销示例...
在上一篇博文中简单介绍了一下BroadcastReceiver的相关知识点,本篇举一个在代码中动态的注册.注销BroadcastReceiver的栗子. 1.首先创建一个MyReceiver并继承Br ...
- Android R system_ext动态扩展分区
Android Q lunch device刷R system.img后,发现其多了个system_ext分区. 列表如下: TPro:/ # ls -l total 65 dr-xr-xr-x 37 ...
- 【Android 高性能音频】Oboe 音频流打开后 耳机 / 音箱 插拔事件处理 ( 动态注册广播接收者监听耳机插拔事件 | 重新打开 Oboe 音频流 )
文章目录 一.动态注册广播接收者监听耳机插拔事件 二.jni 层的 Oboe 播放器代码 ( 重新打开 Oboe 音频流 ) 三.相关资料 基于 [Android 高性能音频]Oboe 开发流程 ( ...
- android的动态注册,Android应用开发之BroadcastReceiver(广播)的静态注册和动态注册 --Android开发...
本文将带你了解Android应用开发之BroadcastReceiver(广播)的静态注册和动态注册 --Android开发,希望本文对大家学Android有所帮助 BroadcastReceiver ...
- Android 第十九课 大喇叭--广播机制----动态注册监听网络变化与静态注册实现开机启动
为了便于进行 系统级别的消息通知,Android引入了一套广播消息机制. 1.广播机制简介: 因为Android中的每个应用程序都可以对自己感兴趣的广播尽心注册,这样程序只会接收自己所关心的广播内容, ...
最新文章
- cfile清空文件内容_电脑C盘文件夹哪些可以删除?教你如何快速清理,旧电脑还能用3年...
- php 验证 e mail,PHP 表单验证 - 验证 E-mail 和 URL
- UrlRewrite(URL重写)--ASP.NET中的实现
- docker 配置nginx镜像出现 403 Forbidden的问题
- 2017.10.25 打鼹鼠 思考记录
- 有多少人欠网贷,往后的日子你打算怎么过?
- java super实例_Java 的 super 学习的一个实例
- 【0702作业】输出九九乘法表
- 信号与线性系统分析(吴大正,郭宝龙)(信号的分类)
- CodeMatic动软自动生成Nhibernate
- Python入门:数据结构之字典(dict)(2)
- 2018百度之星资格赛- 1006 三原色
- 2022年3月15日黑马第三天
- 二十、JVM命令行监控工具
- 优化OpenSearch的搜索结果
- era翻译_era是什么意思_era的翻译_音标_读音_用法_例句_爱词霸在线词典
- Jmeter压测输出可观报告--用表格察看结果(view results in table)输出excel格式
- 不安抗辩权有哪些规定
- unity---Mesh网格编程(四)
- Gimbal Lock
热门文章
- 语言的二义性——编译原理
- Ubuntu系统如何搜索要安装的软件包
- MM们必败潮物。。。。大眼睛的小秘密哦```````
- 版本管理·玩转git(团队合作)
- 用python画卡通图_需要用Python和OpenCV制作一张卡通漫画版的图片
- [深入研究4G/5G/6G专题-40]: URLLC-11-《3GPP URLLC相关协议、规范、技术原理深度解读》-5-5G Qos原理与架构: 切片、PDU会话、QosFlow、5QI、DRB
- 思科交换机路由器 连接配置步骤
- chrome浏览器的性能测试--本文引用自 百度百科http://baike.baidu.com/view/1835504.htm
- 项目管理需要建立团队文化
- window、linux、mac 文件路径禁止字符, 路径长度【全网总结】