潜心静气。。慢慢出成果
全部博文(37)
分类: Android平台
2018-04-12 16:26:43
本文的重点则是讲述,audio从应用层到底层的初始化调用过程:不过重点是在audioTack与AudioFlinger的交互过程。
应用层的几个API重要的类,AudioTrack,AudioRecoder,MediaRecoder,MediaPlayer,
AudioManager等。
MediaRecoder和AudioRecoder都是录音的类,但是MediaRecoder内部有压缩音频源的API,AudioRecoder只是简单的处理原始的音频,相对于录音,则播放音频的则是AudioTrack和MediaPlayer,二者的区别如下:
播放声音可以用MediaPlayer和AudioTrack,两者都提供了java API供应用开发者使用。虽然都可以播放声音,但两者还是有很大的区别的。其中最大的区别是MediaPlayer可以播放多种格式的声音文件,例如MP3,AAC,WAV,OGG,MIDI等。MediaPlayer会在framework层创建对应的音频解码器。而AudioTrack只能播放已经解码的PCM流,如果是文件的话只支持wav格式的音频文件,因为wav格式的音频文件大部分都是PCM流。AudioTrack不创建解码器,所以只能播放不需要解码的wav文件。当然两者之间还是有紧密的联系,MediaPlayer在framework层还是会创建AudioTrack,把解码后的PCM数流传递给AudioTrack,AudioTrack再传递给AudioFlinger进行混音,然后才传递给硬件播放,所以是MediaPlayer包含了AudioTrack。
如下一张图是从网络上看到的,非常全面,摘抄如下:
应用实例:
int frequency = 11025;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
int buffersize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency, channelConfiguration, audioEncoding, buffersize);
byte[]buffer = new byte[buffersize];
audioRecord.startRecording();
audioRecord.read(buffer, 0, bufferReadSize);
audioRecord.stop();
首先这里几个目的:
1>分析AudioTrack和AudioRecoder,并沿着JNI一直分析到audioFlinger,Hardware等:AudioStreamIn和AudioStreamout.
2>丰富Audio调用过程中的几个概念.
以AudioTrack为主线,从audioTrack到HAL的过程分析.Audio系统是一个相对比较复杂的系统,也是一个典型的native的服务,这里我自己的分类为,(1)AMS,PMS,WMS等为JAVA系统级服务,AlamManagerservice等的与硬件操作相关的为插件服务,audio和Surfaceflinger,camera等为native服务。
按照JAVA服务的调用流程,API->aidl->service->jni->hal->kernel.
这里的Native的服务核心则是在native下,JAVA世界只是一个接口,故相当的简单,JAVA世界简单分析。
这里则是讲的是音频播放操作的流程,并不包含应用层stream流的操作。
int bufsize = AudioTrack.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT);
audioplayer =new AudioTrack(AudioManager.STREAM_MUSIC,11025, AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT, bufsize,AudioTrack.MODE_STREAM);
audioplayer.play();
audioplayer.write(buffer, 0 , size);//播放
audioplayer.stop();
int bufsize = AudioTrack.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT);
这个执行的目的则是检测frequency-播放音频的采样率,第二个是音频通道的数量通常指的是播放时几个扬声器等,录音是几个麦克风:
AudioFormat.CHANNEL_CONFIGURATION_MONO;//channelConfiguration
AudioFormat.CHANNEL_CONFIGURATION_STEREO;
AudioFormat.CHANNEL_CONFIGURATION_INVALID;
AudioFormat.CHANNEL_CONFIGURATION_DEFAULT;
第三个是音频的采样精度:
AudioFormat.ENCODING_DEFAULT;//audioEncoding
AudioFormat.ENCODING_INVALID;
AudioFormat.ENCODING_PCM_16BIT; 16个bit相当于两个字节。
AudioFormat.ENCODING_PCM_8BIT;
如此将进入AudioTack.java,这里是只是标记重点的函数。
static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)
这里是音道赋值。
switch(channelConfig) {
case AudioFormat.CHANNEL_OUT_MONO:
case AudioFormat.CHANNEL_CONFIGURATION_MONO:
channelCount = 1;
break;
case AudioFormat.CHANNEL_OUT_STEREO:
case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
channelCount = 2;
break;
检测应用demo输入的sampleRateInHz是否在系统支持的RATE之内。
if ( (sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) ) {
loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate.");
return ERROR_BAD_VALUE;}
如下将进入到android_media_AudioTrack.cpp的世界,这里是JNI调用。这里或许会有个好奇,为什么JAVA世界不能判断完毕,还要进入到native世界,这里主要是与硬件有关的参数,需要进入到native世界才能拿到参数判断。这里的返回值size就是在new AudioTrack时使用的。
int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz,
jint sampleRateInHertz, jint channelCount, jint audioFormat)
这里进入到AudioTrack.cpp里来判断sampleRateInHertz和音频格式是不是适合当前的硬件信息。
const status_t status = AudioTrack::getMinFrameCount(&frameCount,AUDIO_STREAM_DEFAULT,sampleRateInHertz);
audioFormatToNative判断是否支持。
开始进入到第二句的分析:
这里只是开辟一块共享内存,基于/dev/ashmem,具体研究下ashmem的共享内存机制。与binder和log为Android创造的三大机制。
audioplayer =new AudioTrack(AudioManager.STREAM_MUSIC,11025, AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT, bufsize,AudioTrack.MODE_STREAM);
这里只是一个简单的调用,不在太多废话,只是简单介绍一个数据流格式,STREAM_MUSIC和MODE_STREAM
MODE_STREAM模式是针对于音乐播放等时长比较长的播放,比如播放周杰伦的千里之外,就是这种,将音频数据分段多次写入共享内存里,有延时,MODE_STATIC则是针对铃声等短音频,一次将音频数据全部写入。二者的差异则是在共享内存的开辟地点,一个在Audioflinger,一个在audiotrack。
STREAM_MUSIC则是对数据定义,这里大家看到就明白了吧。啰嗦一句,这里划分主要是根据应用的策略有关,因为在audioflinger里,策略决定路由策略,路由策略决定MixerThread,再决定音频播放或者录音设备。
STREAM_MUSIC
STREAM_ALARM
STREAM_RING
STREAM_VOICE_CALL
STREAM_SYSTEM
native_setup
android_media_AudioTrack_setup
switch (memoryMode) {
case MODE_STREAM:
status = lpTrack->set ........
case MODE_STATIC:这里就是STATIC模式在理开辟共享内存。
PS:这里仅仅是介绍流程,很多技术细节,水平有限慢慢专研。共享内存的操作细节有在做分析
// AudioTrack is using shared memory
if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
goto native_init_failure;
}
status = lpTrack->set ........
进入到audioTack.cpp的set函数
status_t AudioTrack::set(........
if (cbf != NULL) {
mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
// thread begins in paused state, and will not reference us until start()
}
这里的mAudioTrackThread主要作用如下:
这个线程是用于AudioTrack(native)与AudioTrack(java)间的数据事件通知的.
status_t status = createTrack_l();....
createTrack_l......这里重点分析的几个函数如下:
这里牵扯到main_audioserver.cpp,在init.*.rc中。以service形式启动,不过在Android6.0以前是在main_mediaserver.cpp中。
这里主要干的事情很简单,1>将服务add servicemanager中,然后new audioflinger和Audiopolicyservice,其中audiopolicyservice中会创建一个新的线程MixerThread。
sp
sp
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
RadioService::instantiate();
SoundTriggerHwService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
这里从audioTrack.cpp进到AudioFlinger.cpp中调用是基于进程间binder机制通信,C++多态的调用机制,看过Android代码的同行应该很熟悉的。
virtual status_t getOutputForAttr.....->
status_t status = remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply);
....
->status_t BnAudioPolicyService::onTransact ....
->audioPolicyservice的getOutputForAttr的函数。这里只是binder机制的初步解释。
IAudioPolicyService.cpp(这里主要是与policy有关,比如输出蓝牙还是耳机,音量大小等)
IAudioTrack.cpp(这里主要是start,stop,play...等接口)
IAudioFlinger.cpp(这里主要是setStreamVolume等)
servicemanager的常见用法,
binder = sm->getService(String16("media.audio_flinger"));
const sp
这里插入一个题外话,初始化过程:
首先Audio系统根据流类型找到对应的路由策略,这里的路由策略指的是如下:
enum routing_strategy{
STRATEGY_MEDIA,
STRATEGY_PHONE,
STRATEGY_SONIFICATION,
STRATEGY_DTMF,
NUM_STRATGEIES
}
AudioPolicyService的主要目的是:
输入输出设备的连接状态,系统的音频策略(strategy)的切换,音量/音频参数的设置
AudioPolicyInterfaceImpl.cpp中定义了AudioPolicyService得到相关函数。
初始化流程如下:
根据流类型找到对应的路由策略
根据该策略找到合适的device(比如扬声器,耳机)
根据device选择合适的工作线程,MixerThread,蓝牙,DSP,DuplicatingThread,
AT根据得到的工作线程索引号,创建一个对方的Track,然后添加到MixerThread中。
status = AudioSystem::getOutputForAttr(attr, &output,
mSessionId, &streamType, mClientUid,
mSampleRate, mFormat, mChannelMask,
mFlags, mSelectedDeviceId, mOffloadInfo);
->这里进入到IAudioPolicyService.cpp的getOutputForAttr,通过binder机制,进入到AudioPolicyService.cpp的getOutputForAttr执行。
-->AudioPolicyInterfaceImpl.cpp 这里定义着AudioPolicyService中很多函数实现。
---> return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, samplingRate,format, channelMask, flags, selectedDeviceId, offloadInfo);
这里的mAudioPolicyManager定义细节如下:AudioPolicyInterface *mAudioPolicyManager;
故根据继承关系可以知道,AudioPolicyInterface类定义了一个纯虚函数getOutputForAttr
class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManagerObserver
---->故最后执行到AudioPolicyManager.cpp的getOutputForAttr。
继续追踪代码发现如下:
----->getOutputForDevice
::mpClientInterface->openOutput:_l
这里的mpClientInterface是执行的AudioPolicyClient.cpp
sp
af->openInput(module, input, config, device, address, source, flags);
继续回到AudioFlinger里分析如下:
openOutput::openOutput
->findSuitableHwDev_l
->loadHwModule_l
->load_audio_interface
: rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
: rc = audio_hw_device_open(mod, dev);
到此,熟悉HAL层的朋友也应该很清楚了,这里就是Hardware层寻找合适的设备。
底下就是厂商的Hardware层了。这里有个文件是audio.c和audio.h承接Hardware的细节。
AudioPolicyService的很大一部分管理工作都是在AudioPolicyManager中完成的。包括音量管理,音频策略(strategy)管理,输入输出设备管理。
由此可见,电话铃声可以有7个级别的音量,而音乐则可以有15个音量级别,java的代码通过jni,最后调用 AudioPolicyManager的initStreamVolume(),把这个数组的内容传入AudioPolicyManager中,这样 AudioPolicyManager也就记住了每一个音频流的音量级别。应用程序可以调用setStreamVolumeIndex设置各个音频流的音量级别,setStreamVolumeIndex会把这个整数的音量级别转化为适合人耳的对数级别,然后通过AudioPolicyService的 AudioCommandThread,最终会将设置应用到AudioFlinger的相应的Track中。
AudioCommandThread
这是AudioPolicyService中的一个线程,主要用于处理音频设置相关的命令。包括:
START_TONE
STOP_TONE
SET_VOLUME
SET_PARAMETERS
SET_VOICE_VOLUME
每种命令的参数有相应的包装:
class ToneData
class VolumeData
class ParametersData
class VoiceVolumeData
START_TONE/STOP_TONE:播放电话系统中常用的特殊音调,例如:TONE_DTMF_0,TONE_SUP_BUSY等等。
SET_VOLUME:最终会调用AudioFlinger进行音量设置
SET_VOICE_VOLUME:最终会调用AudioFlinger进行电话音量设置
SET_PARAMETERS:通过一个KeyValuePairs形式的字符串进行参数设置。
创建track并add到MixerThread中。
sp
这里是binder机制和proxy设计思想的结果,
先是调用IAudioFlinger的BnAudioFlinger,通过binder的transt到onTranst函数,进而通过继承关系最终会调用到AudioFlinger的createTrack
->PlaybackThread *thread = checkPlaybackThread_l(output);
->track = thread->createTrack_l .....
-->track = new Track .....
-->mTracks.add(track);
获得共享内存的细节信息。
sp
play的过程
audiotrack::start
通过mAudioTrack ->start可以知道执行的是bpAudiotrack的start,然后根据继承的关系可以知道,
class TrackHandle : public android::BnAudioTrack
trackHandle = new TrackHandle(track);
mAudioTrack = track;
由此可以知道执行到TrackHandle的start。
return mTrack->start();
这里最终执行到PlaybackThread的addTrack_l
mTrack的定义如下:
const sp
-->status_t AudioFlinger::PlaybackThread::Track::start
---> status = playbackThread->addTrack_l(this);
AudioFlinger::PlaybackThread::addTrack_l
status = AudioSystem::startOutput(mId, track->streamType(),
track->sessionId());
aps->startOutput(output, stream, session);
AudioPolicyService::startOutput
mAudioPolicyManager->startOutput(output, stream, session);
status_t AudioPolicyManager::startOutput
---->mActiveTracks.add(track);
mWaitWorkCV.broadcast();//广播一下,新的Track产生,MixerThread开始工作
mWakeLockUids.add(track->uid());
recoderTrack的track状态。
recordTrack->mState = TrackBase::STARTING_1;
与 recordTrack->mState = TrackBase::PAUSING;
因此对于play和stop,release等API的操作,最终都是通过IAudioTrack.cpp执行到TrackHandle
的start,stop等接口,进而执行到track的start,stop等接。
PlaybackThread与MixerThread都是在AudioFlinger里
当一个PlaybackThread进入主循环后(threadLoop),音频事务就正式开启了。仔细观察的话,我们会发现这个循环中会不断地调用以“threadLoop_”开头的若干接口,比如threadLoop_mix、threadLoop_sleepTime、threadLoop_standby等等。以这样的前缀开头,是因为这些函数都是在threadLoop这个主体里被调用的,可以说代表了这个PlaybackThread所需要完成的各个操作步骤。
MixerThread
继承与PlaybackThread,并部分改写接口函数。
MixerThread--->PlaybackThread--->ThreadBase--->Thread
在Threads.cpp内有几个threadLoop_xxx方法,这些方法就分别代表不同的Audio操作:
操作 |
方法 |
功能 |
standby |
threadLoop_standby |
待机 |
mix |
threadLoop_mix |
混音 |
write |
threadLoop_write |
音频输出 |
exit |
threadLoop_exit |
退出 |
drain |
threadLoop_drain |
只有offload用到,还不清楚作用 |
sleep |
threadLoop_sleepTime |
无音频需要处理,计算睡眠时间 |
AudioCommandThread在AudioPolicyservice里。
将音量,或者设备切换状态信息传给AudioHardWare处理。
AudioTrackThread在AudioTrack.cpp里
这个线程本身就在应用里,给应用汇报当前音频播放状态。
AudioPolicyService:音频策略的制定者,负责音频设备切换的策略抉择、音量调节策略等
AudioFlinger:音频策略的执行者,负责输入输出流设备的管理及音频流数据的处理传输
这里总结下,AudioTrack的new的过程则是根据Stream_Type来决定get route_strategy,进而get strategy for Audio device,创建track 并add到MixerThread中,Static或者Stream Mode决定共享内存是在哪里开辟,然后调用Start或者stop 或者release等最后会调用到Track的start,stop,release等,进而addTrack_l ->mActiveTracks.add(track); 或者broadcast_l->mSignalPending = true;mWaitWorkCV.broadcast();
分析下write的执行过程:
AudioTack.java中的:write
native_write_native_bytes
->android_media_AudioTrack::writeToTrack
如果是stream,这是调用AudioTrack的write
-->written = track->write(data + offsetInSamples, sizeInBytes, blocking);
--->AudioTrack.cpp::obtainBuffer,memcpy(audioBuffer.i8, buffer, toWrite);
如果是Static则是直接memcpy的方式进行。
-->memcpy(track->sharedBuffer()->pointer(), data + offsetInSamples, sizeInBytes);
AudioTrack端作为生产者在共享内存里写入数据后,AudioFlinger端作为消费者读取数据,最后执行MixerThread线程中的threadLoop_write函数,
AudioStreamOut *output = mOutput;
bytesWritten = mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
最后写入到AudioStreamOut里。
简单分析下AudioRecoder的过程:
根据上述AudioRecoder的案例可以知道,
1>getMinBufferSize:
此处函数与AudioTrack一样,计算和硬件参数检测。
->android_media_AudioRecord_get_min_buff_size
-->AudioRecord::getMinFrameCount....
---> AudioSystem::getInputBufferSize
---->根据binder机制AudioFlinger.cpp和IAudioFlinger.cpp,这里就是查询参数。
最终如果return 0时,意味着参数不匹配。
2>new audioRecoder。
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency, channelConfiguration, audioEncoding, buffersize);
-->native_setup
再次进入到native的世界。
--->android_media_AudioRecord_setup
---->audiorecoder.cpp :: set
-----> AudioRecordThread创建并run,不过无论是Track还是Recoder都是start后才开始执行相关线程。
----->openRecord_l
------>AudioSystem::get_audio_flinger()
------>AudioSystem::getInputForAttr
这里的binder机制和proxy模式,分别进入到IAudioPolicyService和AudioPolicyInterfaceImpl的getInputForAttr,这里再强调下,AudioPolicyManager.cpp是AudioPolicyService的音量和policy的具体实现。
进入到AudioPolicyInterfaceImpl的getInputForAttr分析:
AudioPolicyInterface *mAudioPolicyManager;
mAudioPolicyManager->getInputForAttr.........
同一样的套路,进入到AudioPolicyManager执行getInputForAttr,不过这里的目的是什么呢?
mOutputRoutes.addRoute
routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
*output = getOutputForDevice(device, session, *stream,
samplingRate, format, channelMask,
flags, offloadInfo);
上诉依然是根据应用中传入的MIC找合适的getStrategy和 getDeviceForStrategy,
最后执行mpClientInterface->openOutput。
AudioPolicyClientInterface *mpClientInterface;
mpClientInterface = AudioPolicyManagerBase::clientInterface
class AudioPolicyManagerBase: public AudioPolicyInterface
AudioPolicyInterface
class AudioPolicyClient : public AudioPolicyClientInterface
status_t AudioPolicyService::AudioPolicyClient::openInput
sp
af->openInput
AudioFlinger::openInput......
sp
AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
sp
------>audioFlinger->openRecord
class RecordHandle : public android::BnAudioRecord
这里最终则是recordHandle = new RecordHandle(recordTrack);
------>mAudioRecord = record;
这样以后
看到如上步骤,与AudioTrack相似的步骤分析。
byte[]buffer = new byte[buffersize];
audioRecord.startRecording();
AudioFlinger::RecordThread::start
根据binder机制可以知道,执行流程如下:
RecordHandle::start->RecordTrack::start->RecordThread::start
recordTrack->mState = TrackBase::STARTING_2;至于活跃Track
// signal thread to start
mWaitWorkCV.broadcast();广播一个recoderTrack加入,让RecordThread开始干活。
audioRecord.read(buffer, 0, bufferReadSize);
-->lpRecorder->read
--->memcpy(buffer, audioBuffer.i8, bytesRead);
audioRecord.stop();
--->mAudioRecord->stop();
这里的mAudioRecord根binder机制和C++的多态,执行到RecordHandle
---->mRecordTrack->stop();
recordTrack->mState = TrackBase::PAUSING;
mWaitWorkCV.broadcast();
这里的思路是:RecordHandle->RecordThread,这里的track的RecordThread
RecordTrack与AudioTrack的Track一样。
方法类似,按照代码思路很容易找到。
AudioTrackThread:
这个线程会利用audioCallBack这个函数,从用户那里pull数据,如ToneGenator模式就是这样,不过一般模式是push的方式。
与AudioRecordThread
PlaybackThread与RecordThread
AudioCommandThread
mappingsOut[] = {
{AUDIO_DEVICE_OUT_EARPIECE, "EARPIECE"},
{AUDIO_DEVICE_OUT_SPEAKER, "SPEAKER"},
{AUDIO_DEVICE_OUT_WIRED_HEADSET, "WIRED_HEADSET"},
{AUDIO_DEVICE_OUT_WIRED_HEADPHONE, "WIRED_HEADPHONE"},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "BLUETOOTH_SCO"},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, "BLUETOOTH_SCO_HEADSET"},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, "BLUETOOTH_SCO_CARKIT"},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "BLUETOOTH_A2DP"},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,"BLUETOOTH_A2DP_HEADPHONES"},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, "BLUETOOTH_A2DP_SPEAKER"},
{AUDIO_DEVICE_OUT_AUX_DIGITAL, "AUX_DIGITAL"},
{AUDIO_DEVICE_OUT_HDMI, "HDMI"},
{AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,"ANLG_DOCK_HEADSET"},
{AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,"DGTL_DOCK_HEADSET"},
{AUDIO_DEVICE_OUT_USB_ACCESSORY, "USB_ACCESSORY"},
{AUDIO_DEVICE_OUT_USB_DEVICE, "USB_DEVICE"},
{AUDIO_DEVICE_OUT_TELEPHONY_TX, "TELEPHONY_TX"},
{AUDIO_DEVICE_OUT_LINE, "LINE"},
{AUDIO_DEVICE_OUT_HDMI_ARC, "HDMI_ARC"},
{AUDIO_DEVICE_OUT_SPDIF, "SPDIF"},
{AUDIO_DEVICE_OUT_FM, "FM"},
{AUDIO_DEVICE_OUT_AUX_LINE, "AUX_LINE"},
{AUDIO_DEVICE_OUT_SPEAKER_SAFE, "SPEAKER_SAFE"},
{AUDIO_DEVICE_OUT_IP, "IP"},
{AUDIO_DEVICE_OUT_BUS, "BUS"},
{AUDIO_DEVICE_NONE, "NONE"}, // must be last
mappingsIn[] = {
{AUDIO_DEVICE_IN_COMMUNICATION, "COMMUNICATION"},
{AUDIO_DEVICE_IN_AMBIENT, "AMBIENT"},
{AUDIO_DEVICE_IN_BUILTIN_MIC, "BUILTIN_MIC"},
{AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "BLUETOOTH_SCO_HEADSET"},
{AUDIO_DEVICE_IN_WIRED_HEADSET, "WIRED_HEADSET"},
{AUDIO_DEVICE_IN_AUX_DIGITAL, "AUX_DIGITAL"},
{AUDIO_DEVICE_IN_VOICE_CALL, "VOICE_CALL"},
{AUDIO_DEVICE_IN_TELEPHONY_RX, "TELEPHONY_RX"},
{AUDIO_DEVICE_IN_BACK_MIC, "BACK_MIC"},
{AUDIO_DEVICE_IN_REMOTE_SUBMIX, "REMOTE_SUBMIX"},
{AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, "ANLG_DOCK_HEADSET"},
{AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, "DGTL_DOCK_HEADSET"},
{AUDIO_DEVICE_IN_USB_ACCESSORY, "USB_ACCESSORY"},
{AUDIO_DEVICE_IN_USB_DEVICE, "USB_DEVICE"},
{AUDIO_DEVICE_IN_FM_TUNER, "FM_TUNER"},
{AUDIO_DEVICE_IN_TV_TUNER, "TV_TUNER"},
{AUDIO_DEVICE_IN_LINE, "LINE"},
{AUDIO_DEVICE_IN_SPDIF, "SPDIF"},
{AUDIO_DEVICE_IN_BLUETOOTH_A2DP, "BLUETOOTH_A2DP"},
{AUDIO_DEVICE_IN_LOOPBACK, "LOOPBACK"},
{AUDIO_DEVICE_IN_IP, "IP"},
{AUDIO_DEVICE_IN_BUS, "BUS"},
{AUDIO_DEVICE_NONE, "NONE"}, // must be last
};
AudioPolicyservice分析如下:
main_audioserver.cpp
AudioPolicyService::instantiate();
经过分析,最终执行到AudioPolicyservice的onFirstRef
这里是强指针的概念。
mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
// start audio commands thread
mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
// start output activity command thread
mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
int rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
mAudioPolicyClient = new AudioPolicyClient(this);
mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
-->AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
构造函数分析:这里拉出几个重点函数进行分析:
status_t status = mpClientInterface->openOutput
有刚AudioRecoder的分析,这里直接执行了AudioFlinger的openOutput
AudioStreamOut *outputStream = NULL;
这里从AudioPolicyService的接口调用而来。因此AudioPolicyService的实际执行者是AudioPolicyManager 。
class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManagerObserver
class AudioPolicyClient : public AudioPolicyClientInterface
status_t AudioPolicyService::AudioPolicyClient::openOutput
status_t AudioPolicyService::AudioPolicyClient::openInput
这里最终指向AudioFlinger的openOutput和openInput
AudioPolicyService::AudioPolicyClient
status_t status = outHwDev->openOutputStream......
thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
mPlaybackThreads.add(*output, thread);
这里说明AudioOut是在Main_audioserver进程里初始化,并添加,但是AudioIn则是在new AudioRecoder时,但是AudioPolicyManager这里的构造函数里也有AudioFlinger的openInput的接口调用,为啥呢?
以上是设备的定义,余下时间分析AudioManager的分析。