通过rk 代码,分析android 及kernel 中audio 的控制以及binder的流程

本文深入剖析了Android系统中音频控制的工作原理,从kernel层的rk29_i2s.c、dai、platform到codec的注册过程,再到上层的Android框架,包括AudioManager如何通过AIDL与服务端AudioService进行通信。详细介绍了AIDL文件生成的Java接口、Binder通信机制以及ServiceManager如何管理系统服务。整个流程涉及从硬件驱动到用户空间的交互,揭示了Android音频系统的关键组件和交互方式。
摘要由CSDN通过智能技术生成

Kernel:

 

 

rk29_i2s.c     i2s总线设备的驱动程序。

rk30有3个i2s总线设备,分别是定义在devices.c中的三个platform设备,i2s0  i2s1   i2s2,这三个设备在devices.c里面定义。并且在很早就开始加载,他们生成的platform_device设备节点分别是“rk29_i2s.0”、“rk29_i2s.1”、“rk29_i2s.2”。同时还加载了一个platform_device形式的pcm设备“rockchip-audio”。

 

dai

在rk29_i2s.c中,i2s设备驱动程序platform_driver "rk29_i2s"的probe函数中,定义了一个soc_dai_driver   dai,然后会调用snd_soc_register_dai注册一个soc_dai。并且将dai->dev指向rk29_i2s->dev,将dai->driver指向soc_dai_driver   dai。并且将soc_dai加入dai_list。在i2s设备的probe函数中,同时完成对DMA的申请。

 

platform

在rk29_pcm.c中,加载一个名为“rockchip-audio”的platform_driver驱动,从而生成一个platform_device形式的pcm设备“rockchip-audio”。并且在rk29_pcm.c中,定义了一个snd_soc_platform_driver驱动 rockchip_pcm_platform。

在rockchip-audio”的platform_driver驱动的probe函数中,会调用snd_soc_register_platform注册一个soc_platform, 并将此platform->dev指向rockchip->audio.dev, platform->driver 指向rockchip_pcm_platform。并且将此plaform加入platform_list。

 

codec

在rt5631.c中,定义了一个snd_soc_codec_driver  soc_codec_dev_rt5631而在rt5631i2c设备驱动probe中,通过snd_soc_register_codec来注册一个snd_soc_codec  codec,并将codec的dev指向i2c->dev,codec->driver指向i2cdriver,同时为此codec分配cache。并将此codec加入codec_list。需要注意的是,codec存在codec_dai, codec_dai是根据codec的功能(比如能否playback/Capture)来定义的,在snd_soc_register_codec中也会调用snd_soc_register_dai来注册codec_dai。而i2s级的dai称之为cpu_dai。

 

可以在/sys/kernel/debug/asoc,看到已经注册的dais、platforms、codecs。

card

在soc-core.c文件中,定义了一个platform_driver  "soc-audio",并加载此驱动。而soc-audio对应的设备platform_device"soc-audio"则是在rk29_rt5631.c中定义并加载。

rk29_rt5631.c中定义的platform_device"soc-audio"  rk29_snd_device.通过platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29)将snd_soc_card_rk29设为rk29_snd_device的私有数据。snd_soc_card_rk29是一个snd_soc_card,即定义了一个声卡数据。声卡名称为"RK29_RT5631",通过其成员dai_link,指定此声卡对应的dai 、platform、codec。一个声卡可以指定多个dai_link。
platform_driver "soc-audio"的驱动soc_probe函数中,通过platform_get_drvdata获取rk29_snd_device的私有数据,即snd_soc_card结构体,并根据此结构体的配置来注册声卡snd_soc_register_card

snd_soc_card*card = platform_get_drvdata(pdev);

card->dev= &pdev->dev;

snd_soc_register_card(card);加此声卡加入card_list,为snd_soc_pcm_runtime  card->rtd分配存储空间,并将card的配置信息复制到snd_soc_pcm_runtime中,card->rtd是声卡运行时的一个实例,每个dai_link都对应一个card->rtd,并通过snd_soc_instantiate_card实例化声卡,在实例化声卡中,通过soc_bind_dai_link根据dai_link,遍历dai_list、platform_list,codec_list来绑定声卡的各个对应的部分,之后进行最重要的操作soc_probe_dai_link,执行各个dai_link中platform,dai,codec的probe,完成各个模块的初始化操作,并且创建了一个INIT_DELAYED_WORK(&rtd->delayed_work,close_delayed_work);用于超时关闭声卡。这个超时的时间是可以设置的(pmdown_time)。  ret =device_create_file(&rtd->dev, &dev_attr_pmdown_time); 执行soc_post_component_init,主要是对codec驱动的后续完善工作。之后就是最关键的操作,soc_new_pcm创建PCM设备,将pcm赋给card运行时的实例card->rtd,同时根据codec_dai的功能(是否能播音/录音),为pcm设备创建playback substream 和 capture stream。并把rtd->platform(rk29_pcm.c)中定义的pcm的ops赋给此pcm,并且rtd->platform(rk29_pcm.c)中定义的创建pcm回调函数,为playback substream 和 capture stream分配DMA Buffer(这个与平台相关,不是必须)。至此PCM创建完成,以上都是在soc_probe_dai_link中完成。再之后soc_probe_aux_dev加载一些codec的辅助设备,这个通常是没有的。之后是添加DAMP(动态电源控制,通过开关部件实现降功耗)。之后执行card->late_probe,这个通常是没有的。最好,执行完这些操作后,snd_card_register完成声卡注册。

 

 

注意,此时由于dai_list, platform_list可能并未填充。所以,当系统添加dai设备或者platform设备时,都会执行一次实例化声卡的操作。

 

 

soc_core.c中定义了四个双向链表dai_list, card_list,codec_list,  platform_list.  使用LIST_HEAD来定义,这些链表都是双向链表。

 

platform-device.dev是platform-device设备的详细描述。


 

Android

AudioManager.java里面定义各种对音频的操作 ,如加减音量,静音等,这个是最靠近上层的,是被应用程序直接调用的,也是音频控制的唯一的上层借口库。AudioManager中的功能有AudioService来实现。

 

 

aidl:

aidl是Android Interface definition language的缩写,它是一种进程通信接口的描述,通过AIDL工具对aidl文件进行转换,生成一个out目录下的java文件,类路径与aidl文件的类路径相同

./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.java

 

 

 

1.aidl文件IAudioService.aidl中定义service的 Interface。

2.AIDL工具根据aidl文件生成IAudioService.java文件(在out目录下)。

3.IAudioService.java中定义定义一个继承android.os.IInterface的InterfaceIAudioService。

4.IAudioService中定义一个抽象类Stub继承自android.os.Binder,并且实现了onTransact方法。

5.Stub中定义一个静态类Proxy,继承自Interface IAudioService,而这个抽象类中实现了Interface    IAudioService中定义的方法,实现方法都是通过调用transact方法,与服务器端通信,然后获得服务器的响应。

 

IAudioService定义:

publicinterface IAudioService extendsandroid.os.IInterface {

Stub定义:

publicstaticabstractclass Stub extends android.os.Binder implements

        android.media.IAudioService

Proxy定义:

privatestaticclass Proxy implements android.media.IAudioService {

   IAudioService中:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值