第十八篇 ANDROID的声音管理系统及服务
声音管理系统用来实现声音的输入和输出、声音的控制和路由等功能,包括主和各种音源的音量调节、声音焦点控制,声音外设的检测和状态管理,声音源输入和输出的策略管理、音效的播放、音轨设置和播放、录音设置和启动等功能。
整个声音管理系统相关类图如下:主要由JAVA端的系统服务AudioService及两个本地服务声音输入输出策略管理服务AudioPolicyService及声音输出投射服务AudioFlinger来实现相关功能。
应用主要通过AudioManage接口来使用AudioService提供的服务。系统服务AudioService与两个本地服务之间通过AudioSystem类提供的接口借助JNI进行交互。
系统服务AudioService使用蓝牙监听对象BluetoothProfile.ServiceListener来监听蓝牙框架服务HeadsetProfile及HeadsetProfile的连接,并获得两个蓝牙框架服务的客户端对象BluetoothHeadset和BluetoothA2dp来与对应的蓝牙框架服务实现交互。使用一个AudioServiceBroadcastReceiver广播接收对象来监听基座状态事件、蓝牙连接状态改变事件、外设插拔事件、声音状态改变事件、屏幕打开关闭事件、配置改变事件、用户切换事件等事件并进行相应处理。
当检测到需要切换声音路由时,由相关应用通过AudioManage接口调用AudioService系统服务提供的setWiredDeviceConnectionState、setBluetoothA2dpDeviceConnectionState()接口来发起或AudioService系统服务本身检测到相关的事件来触发媒体路由切换,并通过IAudioRoutesObserver接口调用dispatchAudioRoutesChanged()函数来通知媒体路由切换相关进程和服务进行相应处理。
声音焦点控制主要有AudioService系统服务提供的MediaFocusControl对象进行控制。声音焦点控制实现同时只有一个应用能够获得焦点播放同种类型的声音,ANDROID提供和支持STREAM_VOICE_CALL(电话呼叫)、STREAM_SYSTEM(系统)、STREAM_RING(振铃和消息提示)、STREAM_MUSIC(音乐媒体播放)、STREAM_ALARM(警报声)、STREAM_NOTIFICATION(通知音)、STREAM_BLUETOOTH_SCO(蓝牙电话)、STREAM_SYSTEM_ENFORCED(强制系统声音)、STREAM_DTMF(DTMF拨号音)及STREAM_TTS(文本识别音)九种声音流类型,每种类型可以独立的调节声音大小,其中除了STREAM_MUSIC类型是应用播放媒体使用的类型外其它都是系统要处理的声音类型。MediaFocusControl对象的相关类图如下:
本地服务AudioPolicyService提供不同声音流类型对应的输入输出设备的策略获取及策略的选择和控制(输入输出选择、输入输出设备的打开和停止、关闭等)、设置和获取声音设备的连接状态以及不同流类型对应的设备的音量的设置和获取、音频参数的设置、音效设置等功能。类图如下:
AudioPolicyService有一个内部线程类AudioCommandThread,顾名思义,所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行;
在AudioPolicyService实例化时调用audio_policy_dev_open函数打开一个声音策略设备,并通过声音策略设备的create_audio_policy接口返回一个audio_policy策略函数结构体指针,AudioPolicyService对应的函数通过这个audio_policy函数结构体指针调用声音策略设备的对应函数实现设备的策略控制,在AudioPolicyService调用create_audio_policy函数时也把AudioPolicyService内部的一个audio_policy_service_ops函数结构体传给声音策略设备对象,供声音策略设备对象内部调用。声音策略设备使用create_audio_policy函数除了为audio_policy策略函数结构体函数指针赋值以外,还实例了两个对象,一个AudioPolicyClientInterface对象,作为AudioPolicyService客户端使用,声音策略设备使用AudioPolicyClientInterface对象通过AudioPolicyService的内部接口audio_policy_service_op调用AudioPolicyService的相关函数;另外一个对象为具体的实现相关声音策略接口的AudioPolicyInterface对象,这里采用的是设计模式的策略模式,这也是AudioPolicyService称为声音策略服务的原因吧,
AudioPolicyInterface接口的具体实例的创建采用了工厂方法。
下面以AudioPolicyService的getInput函数为例子具体说明整个调用流程。AudioPolicyService的getInput函数实现根据函数传进来的声音输入类型、采样率、声音格式、通道掩码参数打开一个输入设备,整个流程为:
AudioPolicyService的getInput首先通过create_audio_policy获得的audio_policy函数结构体指针调用其get_input函数;
get_input函数然后调用create_audio_policy内部采用工厂方法createAudioPolicyManager创建的具体AudioPolicyInterface对象的getInput函数。
AudioPolicyInterface对象的getInput函数内部首先调用getDeviceForInputSource函数根据函数传进来的输入源类型获得对应的audio_devices_t设备类型,然后调用getInputProfile函数根据传进来的声音采样率、声音格式、通道掩码等参数与获得的设备支持的Input
Profile比较返回一个与设备Profile匹配的IOProfile,然后根据返回的IOProfile对象构造一个AudioInputDescriptor对象添加到输入描述数组中,并调用create_audio_policy内部创建的一个具体AudioPolicyClientInterface对象的openInput函数;AudioPolicyClientInterface对象的openInput函数调用AudioPolicyService内部audio_policy_service_op函数结构体的open_input_on_module函数;
audio_policy_service_op函数结构体的open_input_on_module函数指针指向AudioPolicyService的aps_open_input_on_module函数,因此调用aps_open_input_on_module,aps_open_input_on_module内部首先AudioSystem类的get_audio_flinger函数获得IAudioFlinger接口,然后通过IAudioFlinger接口调用AudioFlinger服务的openInput函数,打开选择的输入设备,返回AudioPolicyService的getInput函数一个audio_io_handle_t句柄;
AudioPolicyService的getInput函数接着根据传进来的audioSession参数构造一个InputDesc对象,把getInput函数返回的audio_io_handle_t句柄添加到向量数组中,根据输入源类型从支持的输入源向量列表获得该输入源支持的EffectDesc数组,并对每一个EffectDesc根据EffectDesc的Uuid、返回的audio_io_handle_t句柄及audioSession参数实例化一个AudioEffect对象,并调用AudioEffect对象的setParameter函数为每一个EffectDesc设置声音参数。每个AudioEffect对象也添加到InputDesc对象AudioEffect的数组中。完成整个流程。
版权所有,转载时请尊重原创显要处注明链接,谢谢!
第十七篇 --ANDROID DisplayManager 服务解析一
第十八篇 ANDROID的声音管理系统及服务的更多相关文章
- Python之路【第十八篇】:Web框架们
Python之路[第十八篇]:Web框架们 Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...
- Egret入门学习日记 --- 第十八篇(书中 8.5~8.7 节 内容)
第十八篇(书中 8.5~8.7 节 内容) 其实语法篇,我感觉没必要写录入到日记里. 我也犹豫了好久,到底要不要录入. 这样,我先读一遍语法篇的所有内容,我觉得值得留下的,我就录入日记里. 不然像昨天 ...
- Android UI开发第二十八篇——Fragment中使用左右滑动菜单
Fragment实现了Android UI的分片管理,尤其在平板开发中,好处多多.这一篇将借助Android UI开发第二十六篇——Fragment间的通信. Android UI开发第二十七篇——实 ...
- Android高手进阶教程(二十八)之---Android ViewPager控件的使用(基于ViewPager的横向相册)!!!
分类: Android高手进阶 Android基础教程 2012-09-14 18:10 29759人阅读 评论(35) 收藏 举报 android相册layoutobjectclassloade ...
- Android笔记(五十八)Android总结:四大组件——Activity篇
什么是Activity Activity是一种包含用户界面的组件,主要用于和用户进行交互,一个APP通常由多个Activity组成. 每个Activity都对应一个布局文件,通过setContentV ...
- Python开发【第十八篇】Web框架之Django【基础篇】
一.简介 Python下有许多款不同的 Web 框架,Django 是重量级选手中最有代表性的一位,许多成功的网站和APP都基于 Django. Django 是一个开放源代码的Web应用框架,由 P ...
- 十八、Android引导界面
一.所需素材 很有必要整理一下,里面附带友盟的社会化分享组件,我就不去掉了. 二.代码 import com.umeng.update.UmengUpdateAgent; import android ...
- 第五十八篇、iOS 微信聊天发送小视频的秘密
对于播放视频,大家应该一开始就想到比较方便快捷使用简单的MPMoviePlayerController类,确实用这个苹果官方为我们包装好了的 API 确实有很多事情都不用我们烦心,我们可以很快的做出一 ...
- python【第十八篇】Django基础
1.什么是Django? Django是一个Python写成的开源Web应用框架.python流行的web框架还有很多,如tornado.flask.web.py等.django采用了MVC的框架模式 ...
随机推荐
- Android开发学习之路--Android Studio项目目录结构简介
既然已经搭建好环境了,那就对Android Studio中项目目录结构做个简单的了解了,这里以最简单的Hello工程为例子,新建好工程后看如下三个工程视图: 1.Android工程 manifests ...
- [django]项目打包构建
django项目的结构大体上都是类似,打包主要的功能就是把一些不需要部署的文件剔除,把需要部署的文件直接压缩打包. 这里还想集成一个配置文件模板生成配置文件的过程,或者写一个配置文件生成的工具,不用每 ...
- CoordinatorLayout 自定义Behavior并不难,由简到难手把手带你撸三款!
先来看看最终的效果~~ 本文同步至博主的私人博客wing的地方酒馆 嗯..一个是头像上移的 另一个是模仿UC浏览器的. (PД`q.)你不是说!有三款的吗,怎么只有两款!!!! 不要急嘛... 说了从 ...
- UNIX网络编程——TCP连接的建立和断开、滑动窗口
一.TCP段格式: TCP的段格式如下图所示: 源端口号与目的端口号:源端口号和目的端口号,加上IP首部的源IP地址和目的IP地址唯一确定一个TCP连接. 序号:序号表示在这个报文段中的第一个数据字节 ...
- .NET 连接SQL Server2012遇到的连接出错问题解析
最近在用VS2013编写相关于SQL Server数据库的代码,但是却遇到了艰难的bug问题,那就是在进行连接的时候出现了各种异常. 出错分析 1.首先应该想到的是数据库的相关服务没有开启. 因为默认 ...
- matlab中 mcc、mbuild和mex命令详解
先简单的说说mcc.mbuild和mex到底怎么回事: mcc将M文件转换成C/C++文件和相应的MEX包裹文件(需要Matlab编辑器),但在特定条件下可以自动调用mbuild或者mex mex将C ...
- chrome "Provisional headers are shown"
我的问题的,每次打开浏览器,点开有视频的页面(云平台的存储),然后当视频还没有加载完,就马上关闭,连续操作很多次(测试的暴力测试把),F12查看就有很多很多在加载中的连接,因为连续点击太多次了,第一个 ...
- HEVC(H.265)标准的编码器(x265,DivX265)试用
基于HEVC(H.265)的的应用级别的编码器发展的速度很快.所说的应用级别,就是指速度比较快的,有实际应用价值的编码器.目前可以直接使用的有两个:x265,DivX265. DivX265 DivX ...
- UILTView经典知识点练习
作者:韩俊强 未经允许,请勿转载! 关注博主:http://weibo.com/hanjunqiang 声明:UILTView 指:UILabel 和 UITextField 的复合 #impor ...
- Python学习笔记 - 数据类型和变量
Python中有整数和浮点数,表示方法和C语言一样 浮点数也很像,不过Python可以用单引号把字符串括起来 字符串是以单引号'或双引号"括起来的任意文本,比如'abc',"xyz ...