今天分析Android的Audio系统时,对mpAudioPolicy->get_input进行了分析,没想到这一句话的背后如此复杂,简直是一句话引出的血案啊!

分析结果如下:(关于排版:各个变量的调用关系的图在博客里屏幕太窄了,可以复制到notepad++中看)

调用mpAudioPolicy的get_input,它是mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy)中赋值的

定义:struct audio_policy_device *mpAudioPolicyDev;

定义:struct audio_policy *mpAudioPolicy;

而audio_policy_dev_open(module, &mpAudioPolicyDev);中将赋值给mpAudioPolicyDev

而audio_policy_dev_open定义如下

static inline int audio_policy_dev_open(const hw_module_t* module,

struct audio_policy_device** device)

{

return module->methods->open(module, AUDIO_POLICY_INTERFACE,

(hw_device_t**)device);

}

看来得找model的来源了

AudioPolicyInterface

|继

|承

AudioPolicyManagerBase

|继

|承

AudioPolicyManagerDefault编译成的audio_policy.default.so//hardware/libhardware_legacy/audio/AudioPolicyManagerDefault.cpp、

|    //AudioPolicyManagerDefault.h

|    //    而audio_policy.default.so又依赖于静态库libaudiopolicy_legacy.a(hardware/libhardware_legacy/audio/Android.mk

|    //中:LOCAL_WHOLE_STATIC_LIBRARIES := libaudiopolicy_legacy)

|    //    libaudiopolicy_legacy.a由 AudioPolicyManagerBase.cpp、AudioPolicyCompatClient.cpp、audio_policy_hal.cpp生成

|    //    HAL_MODULE_INFO_SYM在audio_policy_hal.cpp中定义,下面分析audio_policy_hal.cpp中的内容

|

|

hw_get_module_by_class(id, NULL, module)//id=AUDIO_POLICY_HARDWARE_MODULE_ID,hw_get_module_by_class即会加载audio_policy的HAL的SO,

|    //此从原生系统中找到了audio_policy.stub.so、audio_policy.default.so、audio_policy.msm8960.so

|    //    根据使用getprop命令查看模拟器的系统属性可知,模拟器中将会加载audio_policy.default.so,

|    //相关源码在hardware/libhardware_legacy/audio/目录下

|

|

hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module)//#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy"; 而module的类型为hw_module_t

|

|

module->methods->open(module, AUDIO_POLICY_INTERFACE,(hw_device_t**)device)//audio_policy_dev_open函数中,将hw_device_t类型转换成了

|//audio_policy_device返回给mpAudioPolicyDev

|

|

|

audio_policy_dev_open(module, &mpAudioPolicyDev)

|

|

mpAudioPolicyDev->

create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy)

|

|

mpAudioPolicy->get_input(...)

看audio_policy_hal.cpp中的:

static struct hw_module_methods_t legacy_ap_module_methods = {

open: legacy_ap_dev_open

};

struct legacy_ap_module HAL_MODULE_INFO_SYM = {

module: {

common: {

tag: HARDWARE_MODULE_TAG,

version_major: 1,

version_minor: 0,

id: AUDIO_POLICY_HARDWARE_MODULE_ID,

name: "LEGACY Audio Policy HAL",

author: "The Android Open Source Project",

methods: &legacy_ap_module_methods,

dso : NULL,

reserved : {0},

},

},

};

所以module->methods->open将调用到legacy_ap_dev_open函数

而mpAudioPolicyDev最终将成为legacy_ap_dev_open函数的最后一个参数hw_device_t** device

而由:

dev->device.create_audio_policy = create_legacy_ap;

*device = &dev->device.common;

知mpAudioPolicy成为create_legacy_ap的最后一个参数struct audio_policy **ap

而由:

lap->policy.get_input = ap_get_input;

*ap = &lap->policy;

mpAudioPolicy->get_input(...)最终将变成调用ap_get_input

所以:mpAudioPolicy->get_input将调用hardware/libhardware_legacy/audio/audio_policy_hal.cpp中的ap_get_input函数

下面分析ap_get_input函数它的内容如下:

struct legacy_audio_policy *lap = to_lap(pol);

return lap->apm->getInput((int) inputSource, sampling_rate, (int) format, channelMask,(AudioSystem::audio_in_acoustics)acoustics);

而lap->apm由create_legacy_ap中如下语句创造

lap->apm = createAudioPolicyManager(lap->service_client);

所以此处的apm即new AudioPolicyManagerDefault(lap->service_client)对象,而lap->service_client = new AudioPolicyCompatClient(aps_ops, service);

其中的参数是本cpp中调用create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy)中传入的aps_ops和this参数

AudioPolicyManagerBase由定义知它完全等价于AudioPolicyManagerBase

最终分析结论:mpAudioPolicy->get_input将最终调用hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp中的getInput函数

而在AudioPolicyManagerBase中调用AudioPolicyCompatClient的openInput,在openInput中会根据audio_policy.conf文件的配置信息决定使用什么音频设备,

以此确定audio_module_handle_t的值,

然后又在openInput中又将通过本cpp传入的aps_ops回调本cpp中的aps_open_input_on_module

aps_open_input_on_module中调用AudioFlinger的openInput了

AudioFlinger的openInput会产生一个唯一整数作为audio_io_handle_t

AudioFlinger的openInput还会根据AudioPolicyManagerBase中选出的合适音频设备的audio_module_handle_t来在mAudioHwDevs中查找对应的设备的AudioHwDevice对象inHwDev

找出inHwDev设备后,调用改设备的HAL中的open_input_stream,即audio_hw.c中的adev_open_input_stream

在adev_open_input_stream中构造HAL层的自定义类型stream_in(如stub_stream_in),并在stream_in中植入自己定义的HAL层函数,然后把该stream_in返回AudioFlinger

AudioFlinger使用HAL返回的stream_in以及前面找出的设备的AudioHwDevice构造AF中的AudioStreamIn类型对象input,然后创建一个新的RecordThread线程,

并将该线程以前面传入的audio_io_handle_t做索引存入mRecordThreads中,返回audio_io_handle_t,即audio_io_handle_t是在AudioFlinger中找出对应线程的索引

(原)一句mpAudioPolicy->get_input引发的血案的更多相关文章

  1. 转:一个Sqrt函数引发的血案

    转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/1844725.html 源码下载地址:http://diducoder.com/sotr ...

  2. 一个Sqrt函数引发的血案(转)

    作者: 码农1946  来源: 博客园  发布时间: 2013-10-09 11:37  阅读: 4556 次  推荐: 41   原文链接   [收藏]   好吧,我承认我标题党了,不过既然你来了, ...

  3. 【转载】一个Sqrt函数引发的血案

    转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html 源码下载地址:http://diducoder ...

  4. 一个Sqrt函数引发的血案

    源码下载地址:http://diducoder.com/sotry-about-sqrt.html 好吧,我承认我标题党了,不过既然你来了,就认真看下去吧,保证你有收获. 我们平时经常会有一些数据运算 ...

  5. elasticsearch5.0.1集群一次误删除kibana索引引发的血案

    elasticsearch集群中一次删除kibana索引引发的血案 1.问题发生的过程: 早上的时候有某个索引无法看到报表数据,于是就点该报表多次,估计集群被点挂了,报错:Elasticsearch ...

  6. 一个无锁消息队列引发的血案(五)——RingQueue(中) 休眠的艺术

    目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...

  7. 一个无锁消息队列引发的血案(四)——月:RingQueue(上) 自旋锁

    目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...

  8. 一个无锁消息队列引发的血案(三)——地:q3.h 与 RingBuffer

    目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...

  9. 一个由正则表达式引发的血案 vs2017使用rdlc实现批量打印 vs2017使用rdlc [asp.net core 源码分析] 01 - Session SignalR sql for xml path用法 MemCahe C# 操作Excel图形——绘制、读取、隐藏、删除图形 IOC,DIP,DI,IoC容器

    1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ...

  10. 一次"内存泄漏"引发的血案

    本文转载自一次"内存泄漏"引发的血案 导语 2017年末,手Q春节红包项目期间,为保障活动期间服务正常稳定,我对性能不佳的Ark Server进行了改造和重写.重编发布一段时间后, ...

随机推荐

  1. 【转】【WPF】WPF绑定用法

    一.简介 为了后面行文顺利,在进入正文之前,我们首先对本文所涉及到的绑定知识进行简单地介绍.该节包含绑定的基本组成以及构建方式. WPF中的绑定完成了绑定源和绑定目标的联动.一个绑定常常由四部分组成: ...

  2. Mac 下 Homebrew(类似CentOS下的yum)简介及安装

    Homebrew官网 http://brew.sh/index_zh-cn.html Homebrew是神马 linux系统有个让人蛋疼的通病,软件包依赖,好在当前主流的两大发行版本都自带了解决方案, ...

  3. struts2系列(二):struts2参数传递错误、struts2的输入错误验证

    一.struts2参数传递错误 1. 基本数据类型的传递最好使用包装类,原因是struts 2.1之后使用基本数据类型如果参数为空会报错2. 日期参数的传递最好定义一个区域的属性(定义locale), ...

  4. e808. 建立菜单栏,菜单,菜单项

    When the user selects a menu item, it fires an action event. // Create the menu bar JMenuBar menuBar ...

  5. 指定webapi 返回 json 格式 ; GlobalConfiguration.Configuration.Formatters.Clear()

    因为 Internet Explorer 和 Firefox 发送了不同的 Accept 头,所以 web API 在响应里就发送了不同的内容类型.   解决方法,在 Global.asax的 App ...

  6. 使用Spring.NET的IoC容器

    使用Spring.NET的IoC容器 0. 辅助类库 using System; using System.Collections.Generic; using System.Linq; using ...

  7. C# 执行CMD命令的方法

    /// <summary> /// 执行CMD命令 /// </summary> /// <param name="str"></para ...

  8. HTML5 3D Google搜索 小盒子 大世界

    HTML5真是能让人想象万千,居然动起了Google搜索的主意,它利用HTML5技术将Google搜索放到了一个小盒子里,弄起了3D搜索.随着鼠标移动,HTML5 3D搜索盒子也就转动,非常立体.点击 ...

  9. Java对象的序列化与反序列化-Json篇

    说到Java对象的序列化与反序列化,我们首先想到的应该是Java的Serializable接口,这玩意在两个系统之间的DTO对象里面可能会用到,用于系统之间的数据传输.或者在RPC(远程方法调用)时可 ...

  10. 视锥体(frustum)裁剪

    原文地址:http://www.linuxgraphics.cn/graphics/opengl_view_frustum_culling.html 背景 视锥体(frustum),是指场景中摄像机的 ...