(原)一句mpAudioPolicy->get_input引发的血案
今天分析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引发的血案的更多相关文章
- 转:一个Sqrt函数引发的血案
转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/1844725.html 源码下载地址:http://diducoder.com/sotr ...
- 一个Sqrt函数引发的血案(转)
作者: 码农1946 来源: 博客园 发布时间: 2013-10-09 11:37 阅读: 4556 次 推荐: 41 原文链接 [收藏] 好吧,我承认我标题党了,不过既然你来了, ...
- 【转载】一个Sqrt函数引发的血案
转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html 源码下载地址:http://diducoder ...
- 一个Sqrt函数引发的血案
源码下载地址:http://diducoder.com/sotry-about-sqrt.html 好吧,我承认我标题党了,不过既然你来了,就认真看下去吧,保证你有收获. 我们平时经常会有一些数据运算 ...
- elasticsearch5.0.1集群一次误删除kibana索引引发的血案
elasticsearch集群中一次删除kibana索引引发的血案 1.问题发生的过程: 早上的时候有某个索引无法看到报表数据,于是就点该报表多次,估计集群被点挂了,报错:Elasticsearch ...
- 一个无锁消息队列引发的血案(五)——RingQueue(中) 休眠的艺术
目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...
- 一个无锁消息队列引发的血案(四)——月:RingQueue(上) 自旋锁
目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...
- 一个无锁消息队列引发的血案(三)——地:q3.h 与 RingBuffer
目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...
- 一个由正则表达式引发的血案 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. 一些特殊字符,如“&”,“- ...
- 一次"内存泄漏"引发的血案
本文转载自一次"内存泄漏"引发的血案 导语 2017年末,手Q春节红包项目期间,为保障活动期间服务正常稳定,我对性能不佳的Ark Server进行了改造和重写.重编发布一段时间后, ...
随机推荐
- JAXB解析xml
废话不多说,直接上代码 核心类: package com.jaxb; import java.io.File; import java.io.FileInputStream; import java. ...
- Simsimi 小黄鸡机器人最新无限制接口api simsimi机器人接口api 微信公众号
一.什么是Simsimi? simsimi公司是提供智能服务,其中一个服务是simsimi聊天机器人服务,每天有超过百万的用户聊天,国内最大的搜索引擎——百度的产品siri使用的就是simsimi提供 ...
- SpringBoot系列九:SpringBoot服务整合(整合邮件服务、定时调度、Actuator监控)
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 服务整合 2.背景 在进行项目开发的时候经常会遇见以下的几个问题:需要进行邮件发送.定时的任务调 ...
- 多媒体开发之ftp---一个很现实的需求把ftp转换成rtmp协议做点播
http://www.dy2018.com/i/96131.html# http://www.hdpfans.com/thread-15684-1-1.html ftp://xc:xc@dz.dl12 ...
- Keystone-manage 命令
本文介绍Icehouse发行版的keystone-manage命令 keystone-manage是用来同keystone服务进行交互的命令行工具,通常该命令只用于不能通过HTTP API完成的操作, ...
- Android Notification和权限机制探讨
近期为了在部门内做一次小型的技术分享.深入了解了一下Notification的实现原理.以及android的权限机制.在此做个记录.文章可能比較长,没耐心的话就直接看题纲吧. 先看一下以下两张图 图一 ...
- eclipse debug 执行到断点处并没有停下,断点无效问题
转自:http://blog.csdn.net/cuidiwhere/article/details/14434439 现象: 利用eclipse debug时,执行到断点处并没有停下.正常情况下,在 ...
- 设置 sqlserver Profiler 只监控 EF的sql执行请求
当我们用EF执行语句的时候,可以使用 sqlserver Profiler来监控到底执行了哪些sql语句,但是默认他是监控全局的,我们只想监控Ef的语句,这里如下设置 这样就只会监控 EF产生的 sq ...
- 【git】git pull
http://www.01happy.com/git-resolve-conflicts/
- jQuery实现自动调用和触发某个事件的方法
1.比如我们通过jquery定义了一个点击事件,我们如何自动触发他: $(function(){ $('#button').click(function(){ alert('butto ...