08.音频系统:第004课_Android音频系统详解:第007节_AudioPolicyManager堪误与回顾

上小节我们对AudioTrack创建作了一些概述,知道其大概会做如下事情:
1 使用AudioTrack的属性, 根据AudioPolicy找到对应的output、playbackThread
2 在playbackThread中创建对应的track
3 APP的AudioTrack 和 playbackThread的mTracks中的track之间建立共享内存

第一点

我们先来讲解第一点,应用程序在创建AudioTrack时,会指定声音的某些参数,如声音的类型,那么他是怎么找到对应的硬件进行播放的呢?或者说他怎么去选择一个output,这就是该小节要讲解的内容。在讲解之前,我们需要纠正一个错误,只之前的08.音频系统:第004课_Android音频系统详解:第003节_所涉及文件形象讲解,章节说:
在这里插入图片描述
厂家也可以参与策略,其实通过AudioPolicyManagerBase这个基类派生出来厂家的代码AudioPolicyManager.cpp。我们要进行纠正,其实老的方法,那么新的方法是怎么样的呢?其文件为frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager
系统已经实现了该文件,厂家不需要参与策略。即为新方法。打开AudioPolicyService.cpp:

void AudioPolicyService::onFirstRef()
/*可以看到如下宏:使用旧的策略*/
#ifdef USE_LEGACY_AUDIO_POLICY	
	......
#else//新策略
        mAudioPolicyClient = new AudioPolicyClient(this);
        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
#endif

其使用createAudioPolicyManager创建管理者,我们搜索该函数,可以找到android in AudioPolicyFactory.cpp(经过试验证明,我们使用的是该文件):

extern "C" AudioPolicyInterface* createAudioPolicyManager(
	return new AudioPolicyManager(clientInterface);
	

现在我们回顾一下创建AudioFlinger与AudioPolicyService中所作的工作,其所作的工作,是AudioTrack选择output的基础。怎么进行回顾呢?根据上上面我们找到AudioPolicyManager.cpp文件,进入其构造函数(他做的工作与AudioPolicyManagerBase基本一致):

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
	/*加载配置文件,构造mHwmodule*/
	ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config)
	/*根据名字加载mHwmodule对应的so文件,该文件由参加提供*/
	mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());
	/*从mHwmodule获得outProfile */
	const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j];
	/*根据outProfile 得到一个描述符,设置mpClientInterface*/
	sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,mpClientInterface);
	/*打开output设备,同时会创建playbackthread,其会得到一个output整数(该函数的参数),这个整数会对应播放线程,也可以对应SwAudioOutputDescriptor*/
	status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),&output,&config,&outputDesc->mDevice,address,&outputDesc->mLatency,outputDesc->mFlags);
	/*根据output添加outputDesc描述符*/
	addOutput(output, outputDesc);
		outputDesc->setIoHandle(output);
	    mOutputs.add(output, outputDesc);
	    updateMono(output); // update mono status when adding to output list
	    nextAudioPortGeneration();

在这里插入图片描述

1.在AudioPolicyService中存在一个mHwModules数组,其中有多个mHwModule,每个mHwModule包含.mName,.mOutputProfiles(对应一个output结点配置:IOProfiles类),.mInputProfiles(对应一个或者多个input结点配置:IOProfiles类).等成员。
2.由AudioFlinger实现,根据mHwModules数组中每个mHwModule的名字,打开厂家提供的so文件。然后构建硬件封装的对象mAudioHwDevice放入mAudioHwDevices数组中。mAudioHwDevice中含有audio_hw_device结构体,audio_hw_device又包含了厂家提供的AudioHardWare对象。
3.打开module中的output创建playbackTraad线程(由AudioFlinger实现,但是由AudioPolicyService调用):对每一个module中的每一个output Profiles,如果flog不是特殊的,则调用status_t status = outHwDev->openOutputStream(&outputStream,*output,devices,flags,config,address.string())。然后创建线程thread = new DirectOutputThread,在通过mPlaybackThreads.add(*output, thread)添加到mPlaybackThreads线程数组之中。所以,没一个Output都对应一个线程(猜测input也是如此)。
4.把outputDesc放入AudioPolicyManager中的.mOutputs中,以后可以根据一个整数(Output),找到对应的线程,找到对应的outputDesc。outputDesc中含有配置文件的信息。mOutputs表示的是已经打开的mOutput。

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
经典的andriod入门必学一,堂复习 1,什么是安卓? 一款开源的基于linux的操作系统 2,安卓的体系结构 上层:基于java的应用程序开发 中间层:虚拟机Dalvik 底层:基于linux的C++编程 3,安卓的开发环境(IDE) 1,eclipse adt:让eclipse具备开发安卓的功能,是一个插件 android sdk:安卓开发工具包19.0 2,AndroidStudio android sdk:安卓开发工具包 22.0 二,安卓的工程目录 scr/包名/Activity:主要存放代码的目录 gen:(Generated Java Files)自动生成的java文件 assets:资产,存放大型数据文件,Html,css,音频,视频,大型的图片等文件 bin:程序编译完成之后生成的文件存放的目录,也是系统自动生成的 libs:存放第三方的jar包的目录 res:resource资源,图片,声音,文字,视图等等 drawable:图片资源 layout:布局视图文件存放的目录 menu:菜单 values:存放数值类型的资源。比如尺寸,文字,样式 AndroidManifest.xml:安卓app的配置,包括sdk,版本,四大组件的注册,权限等等 三,安卓工程的创建 1,点了一个花菜(创建了一个安卓应用程序的工程) 2,指派一名厨师(创建一个Activity必须继承Activity组件) 3,注册厨师(在AndroidMenifest.xml中注册Activity) 4,构思食材(在res/layout中,创建一个视图) 5, 找老王要菜,老王给了一个单子(在gen/R.java中生成的地址) 6,将食材拿到厨房中(在Activity中,创建onCreate方法,并且在其中,使用setContentView显示的视图) 7,做菜(就是通过findViewById找到对应的控件,执行操作) src:代码存放的地方 gen:自动生成控件的地址R.java res/layout:布局的设计图(通过setContentView才可以在Activity中显示) AndroidMenifest.xml目录,用于注册Activity 四,布局 LinearLayout:方向:(横和竖) 任何的控件,任何的布局都需要 layout_height layout_width 用于确定元素在当前空间中的大小 match_parent:和父类容器一样大 wrap_content:自己多大,就占多大空间 <requestFocus />用于请求光标
在Python中,包是一种组织Python模块的方法,它将相关的模块组合在一起,形成一个大的模块。包可以包含子包和模块,以及其他资源文件。 在一个包目录中,通常会有一个名为`__init__.py`的文件。这个文件的主要作用是标识该目录为Python包,同时可以在其中编写一些初始化代码。 `__init__.py`可以为空文件,也可以包含Python代码。如果`__init__.py`文件存在,则在导入包时会自动执行其中的代码。这就使得我们可以在包的初始化过程中完成一些需要执行的操作,例如设置环境变量、导入必要的模块等。 例如,如果我们有一个名为`mypackage`的包,那么它的目录结构可能如下所示: ``` mypackage/ __init__.py module1.py module2.py ``` 其中,`__init__.py`可以包含一些初始化代码,例如: ```python # 在 __init__.py 中导入模块 from .module1 import * from .module2 import * ``` 这样,在导入`mypackage`包时,就会自动导入`module1`和`module2`模块。 此外,`__init__.py`还可以定义包级别的变量和函数,供包内的模块使用。例如: ```python # 定义包级别的变量 PI = 3.14 # 定义包级别的函数 def square(x): return x ** 2 ``` 这样,在包内的模块中,我们就可以直接使用`mypackage.PI`和`mypackage.square()`来访问这些变量和函数了。 总之,`__init__.py`文件是Python包的重要组成部分,它可以帮助我们更好地组织和管理Python代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江南才尽,年少无知!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值