声音管理系统用来实现声音的输入和输出、声音的控制和路由等功能,包括主和各种音源的音量调节、声音焦点控制,声音外设的检测和状态管理,声音源输入和输出的策略管理、音效的播放、音轨设置和播放、录音设置和启动等功能。

整个声音管理系统相关类图如下:主要由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函数实现根据函数传进来的声音输入类型、采样率、声音格式、通道掩码参数打开一个输入设备,整个流程为:

  1. AudioPolicyService的getInput首先通过create_audio_policy获得的audio_policy函数结构体指针调用其get_input函数;

  2. get_input函数然后调用create_audio_policy内部采用工厂方法createAudioPolicyManager创建的具体AudioPolicyInterface对象的getInput函数。

  3. AudioPolicyInterface对象的getInput函数内部首先调用getDeviceForInputSource函数根据函数传进来的输入源类型获得对应的audio_devices_t设备类型,然后调用getInputProfile函数根据传进来的声音采样率、声音格式、通道掩码等参数与获得的设备支持的Input
    Profile比较返回一个与设备Profile匹配的IOProfile,然后根据返回的IOProfile对象构造一个AudioInputDescriptor对象添加到输入描述数组中,并调用create_audio_policy内部创建的一个具体AudioPolicyClientInterface对象的openInput函数;

  4. AudioPolicyClientInterface对象的openInput函数调用AudioPolicyService内部audio_policy_service_op函数结构体的open_input_on_module函数;

  5. 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的声音管理系统及服务的更多相关文章

  1. Python之路【第十八篇】:Web框架们

    Python之路[第十八篇]:Web框架们   Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...

  2. Egret入门学习日记 --- 第十八篇(书中 8.5~8.7 节 内容)

    第十八篇(书中 8.5~8.7 节 内容) 其实语法篇,我感觉没必要写录入到日记里. 我也犹豫了好久,到底要不要录入. 这样,我先读一遍语法篇的所有内容,我觉得值得留下的,我就录入日记里. 不然像昨天 ...

  3. Android UI开发第二十八篇——Fragment中使用左右滑动菜单

    Fragment实现了Android UI的分片管理,尤其在平板开发中,好处多多.这一篇将借助Android UI开发第二十六篇——Fragment间的通信. Android UI开发第二十七篇——实 ...

  4. Android高手进阶教程(二十八)之---Android ViewPager控件的使用(基于ViewPager的横向相册)!!!

      分类: Android高手进阶 Android基础教程 2012-09-14 18:10 29759人阅读 评论(35) 收藏 举报 android相册layoutobjectclassloade ...

  5. Android笔记(五十八)Android总结:四大组件——Activity篇

    什么是Activity Activity是一种包含用户界面的组件,主要用于和用户进行交互,一个APP通常由多个Activity组成. 每个Activity都对应一个布局文件,通过setContentV ...

  6. Python开发【第十八篇】Web框架之Django【基础篇】

    一.简介 Python下有许多款不同的 Web 框架,Django 是重量级选手中最有代表性的一位,许多成功的网站和APP都基于 Django. Django 是一个开放源代码的Web应用框架,由 P ...

  7. 十八、Android引导界面

    一.所需素材 很有必要整理一下,里面附带友盟的社会化分享组件,我就不去掉了. 二.代码 import com.umeng.update.UmengUpdateAgent; import android ...

  8. 第五十八篇、iOS 微信聊天发送小视频的秘密

    对于播放视频,大家应该一开始就想到比较方便快捷使用简单的MPMoviePlayerController类,确实用这个苹果官方为我们包装好了的 API 确实有很多事情都不用我们烦心,我们可以很快的做出一 ...

  9. python【第十八篇】Django基础

    1.什么是Django? Django是一个Python写成的开源Web应用框架.python流行的web框架还有很多,如tornado.flask.web.py等.django采用了MVC的框架模式 ...

随机推荐

  1. Oracle 执行计划(Explain Plan) 说明

    如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQL的每一步执行是否存在问题. 如果一条SQL平时执行的好好的,却有一天突然性能很差,如果排除了系统资源和阻塞的原因,那么基本可以 ...

  2. EBS接口程序调试

    这两天在做采购接收的时候有一个香港的业务实体的采购接不进去,但是其他业务实体能接进去,找错误话费了不少时间,也参考了网上好多资料,虽然最后这个方法没用但觉得还是很有用的,整理一下作为自己的一个总结 错 ...

  3. Nginx模块之SessionSticky

    0 工作原理 Session Sticky 模块在upstream 返回响应后,向客户的浏览器写入 Cookie ,默认名为route ,保存的内容是一个 md5 码. 之后,模块接收到客户浏览器的请 ...

  4. Android简易实战教程--第四话《最简单的短信发送器》

    首先配置一个布局: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmln ...

  5. Android的ImageView介绍-android学习之旅(二十二)

    ImageView简介 imageView继承于View,主要用于显示图片,凡是Drawable对象都可以用它显示. ImageView直接派生了ImageButton和ZoomButton等组件. ...

  6. 记录github出错及解决方案

    刚刚在github上更新自己项目的一些内容时出现了一些错误,几经折腾及在网上查找资料终于解决.具体记录如下: 主要就是就是在push时报错,错误信息如下: 根据报错信息原本以为是要重新pull一下,但 ...

  7. 最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  8. UNIX环境高级编程——线程

    线程包含了表示进程内执行环境必需的信息,其中包括进程中标示线程的线程ID.一组寄存器值.栈.调度优先级和策略.信号屏蔽字.errno变量以及线程私有数据. 进程的所有信息对该进程的所有线程都是共享的, ...

  9. 海量数据挖掘MMDS week6: 决策树Decision Trees

    http://blog.csdn.net/pipisorry/article/details/49445465 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  10. TCP的定时器系列 — 超时重传定时器

    主要内容:TCP定时器概述,超时重传定时器.ER延迟定时器.PTO定时器的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd Q:一条TCP连接会使用 ...