新聞中心
一 目的

我們提供的服務(wù)有:做網(wǎng)站、網(wǎng)站制作、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、精河ssl等。為近千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的精河網(wǎng)站制作公司
上回我們說了AudioFlinger(AF),總感覺代碼里邊有好多東西沒說清楚,心里發(fā)毛。就看了看AF的流程,我們敢說自己深入了解了Android系統(tǒng)嗎?AudioPolicyService(APS)是個什么東西?為什么要有它的存在?下層的Audio HAL層又是怎么結(jié)合到Android中來的?更有甚者,問個實在問題:插入耳機(jī)后,聲音又怎么從最開始的外放變成從耳機(jī)輸出了?調(diào)節(jié)音量的時候到底是調(diào)節(jié)Music的還是調(diào)節(jié)來電音量呢?這些東西,我們在AF的流程中統(tǒng)統(tǒng)都沒講到。但是這些他們又是至關(guān)重要的。從我個人理解來看,策略(Policy)比流程更復(fù)雜和難懂。
當(dāng)然,遵循我們的傳統(tǒng)分析習(xí)慣,得有一個切入點,否則我們都不知道從何入手了。
這里的切入點將是:
l AF和APS系統(tǒng)第一次起來后,到底干了什么。
l 檢測到耳機(jī)插入事件后,AF和APS的處理。
大家跟著我一步步來看,很快就發(fā)現(xiàn),啊哈,APS也不是那么難嘛。
另外,這次代碼分析的格式將參考《Linux內(nèi)核情景分析》的樣子,函數(shù)調(diào)用的解析將采用深度優(yōu)先的辦法,即先解釋所調(diào)用的函數(shù),然后再出來繼續(xù)講。
我曾經(jīng)數(shù)度放棄分析APS,關(guān)鍵原因是我沒找到切入點,只知道代碼從頭看到尾!
二 AF和APS的誕生
這個東西,已經(jīng)說得太多了。在framework/base/media/MediaServer/Main_MediaServer中。
我們看看。
- int main(int argc, char** argv)
- {
- sp
proc(ProcessState::self()); - sp
sm = defaultServiceManager(); - //先創(chuàng)建AF
- AudioFlinger::instantiate();
- //再創(chuàng)建APS
- AudioPolicyService::instantiate();
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- }
2.1 new AudioFlinger
前面說過,instantiate內(nèi)部會實例化一個對象,那直接看AF的構(gòu)造函數(shù)。
- AudioFlinger::AudioFlinger()
- : BnAudioFlinger(),//基類構(gòu)造函數(shù)
- mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0)
- {
注意mAudioHardware和mNextThreadId
mHardwareStatus = AUDIO_HW_IDLE;
//創(chuàng)建audio的HAL代表
mAudioHardware = AudioHardwareInterface::create();
mHardwareStatus = AUDIO_HW_INIT;
//下面這些不至于會使用APS吧?APS還沒創(chuàng)建呢!
- if (mAudioHardware->initCheck() == NO_ERROR) {
- setMode(AudioSystem::MODE_NORMAL);
- setMasterVolume(1.0f);
- setMasterMute(false);
- }
感覺上,AF的構(gòu)造函數(shù)就是創(chuàng)建了一個最重要的AudioHardWare的HAL代表。
其他好像是沒干什么策略上的事情。
不過:AF創(chuàng)建了一個AudioHardware的HAL對象。注意整個系統(tǒng)就這一個AudioHardware了。也就是說,不管是線控耳機(jī),藍(lán)牙耳機(jī),麥克,外放等等,最后都會由這一個HAL統(tǒng)一管理。
再看APS吧。
2.2 new AudioPolicyService
- AudioPolicyService::AudioPolicyService()
- : BnAudioPolicyService() , mpPolicyManager(NULL)
- {
- // mpPolicyManager?策略管理器?可能很重要
- char value[PROPERTY_VALUE_MAX];
- // TonePlayback?播放鈴聲的?為什么放在這里?以后來看看
- mTonePlaybackThread = new AudioCommandThread(String8(""));
- // Audio Command?音頻命令?看到Command,我就想到設(shè)計模式中的Command模式了
- //Android尤其是MediaPlayerService中大量使用了這種模式。
- mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
- #if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
- //注意AudioPolicyManagerBase的構(gòu)造函數(shù),把this傳進(jìn)去了。
- mpPolicyManager = new AudioPolicyManagerBase(this);
- //先假設(shè)我們使用Generic的Audio設(shè)備吧。
- #else
- ...
- #endif
// 根據(jù)系統(tǒng)屬性來判斷攝像機(jī)是否強(qiáng)制使用聲音。這個...為什么會放在這里?
//手機(jī)帶攝像機(jī)好像剛出來的時候,為了防止偷拍,強(qiáng)制按快門的時候必須發(fā)出聲音
//就是這個目的吧?
- property_get("ro.camera.sound.forced", value, "0");
- mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
- }
so easy!,不至于吧?我們不應(yīng)該放過任何一個疑問!這么多疑問,先看哪個呢?這里分析的是Audio Policy,而構(gòu)造函數(shù)中又創(chuàng)建了一個AudioPolicyManagerBase,而且不同廠商還可以實現(xiàn)自己的AudioPolicyManager,看來這個對于音頻策略有至關(guān)重要的作用了。
不得不說的是,Android代碼中的這些命名在關(guān)鍵地方上還是比較慎重和準(zhǔn)確的。
另外,AudioPolicyManagerBase的構(gòu)造函數(shù)可是把APS傳進(jìn)去了,看來又會有一些回調(diào)靠APS了。真繞。
2.3 AudioPolicyManagerBase
代碼位置在framework/base/libs/audioflinger/AudioPolicyManagerBase.cpp中
- AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
- :
- mPhoneState(AudioSystem::MODE_NORMAL), ---->這里有電話的狀態(tài)?
- mRingerMode(0),
- mMusicStopTime(0),
- mLimitRingtoneVolume(false)
- {
- [--->mPhoneState(AudioSystem::MODE_NORMAL)]
AudioSystem其實是窺視Android如何管理音頻系統(tǒng)的好地方。位置在
framework/base/include/media/AudioSystem.h中,定義了大量的枚舉之類的東西來表達(dá)Google對音頻系統(tǒng)的看法。我們只能見招拆招了。
下面是audio_mode的定義。這里要注意一個地方:
這些定義都和SDK中的JAVA層定義類似。實際上應(yīng)該說先有C++層的定義,然后再反映到JAVA層中。但是C++層的定義一般沒有解釋說明,而SDK中有。所以我們不能不面對的一個痛苦現(xiàn)實就是:常常需要參考SDK的說明才能搞明白到底是什么。
關(guān)于C++的AudioSystem這塊,SDK的說明在AudioManager中。
- enum audio_mode {
- //解釋參考SDK說明,以下不再說明
- MODE_INVALID = -2, //無效mode
- MODE_CURRENT = -1,//當(dāng)前mode,和音頻設(shè)備的切換(路由)有關(guān)
- MODE_NORMAL = 0,//正常mode,沒有電話和鈴聲
- MODE_RINGTONE,//收到來電信號了,此時會有鈴聲
- MODE_IN_CALL,//電話mode,這里表示已經(jīng)建立通話了
- NUM_MODES // Android大量采用這種技巧來表示枚舉結(jié)束了。
- };
好,繼續(xù):
- ...
- mPhoneState(AudioSystem::MODE_NORMAL), ---->這里有電話的狀態(tài)?
- mRingerMode(0),
- mMusicStopTime(0),
- mLimitRingtoneVolume(false)
- {
- mpClientInterface = clientInterface;//BT,保存APS對象。
- //forceUse?這是個什么玩意兒?
- for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
- mForceUse[i] = AudioSystem::FORCE_NONE;
- }
[---->AudioSystem::FORCE_NONE和AudioSystem::NUM_FORCE_USE]
注意,這里有兩個枚舉,太無恥了。先看看FORCE_NONE這個
- enum forced_config {強(qiáng)制_配置,看名字好像是強(qiáng)制使用設(shè)備吧,比如外放,耳機(jī),藍(lán)牙等
- FORCE_NONE,
- FORCE_SPEAKER,
- FORCE_HEADPHONES,
- FORCE_BT_SCO,
- FORCE_BT_A2DP,
- FORCE_WIRED_ACCESSORY,
- FORCE_BT_CAR_DOCK,
- FORCE_BT_DESK_DOCK,
- NUM_FORCE_CONFIG,
- FORCE_DEFAULT = FORCE_NONE //這個,太無聊了。
- };
再看看AudioSystem::NUM_FORCE_USE這個
- enum force_use {
- FOR_COMMUNICATION,//這里是for_xxx,不是force_xxx。
- FOR_MEDIA,
- FOR_RECORD,
- FOR_DOCK,
- NUM_FORCE_USE
- };
不懂,兩個都不懂。為何?能猜出來什么嗎?也不行。因為我們沒找到合適的場景!那好吧,我們?nèi)DK找找。恩
我看到AudioManager這個函數(shù)setSpeakerphoneOn (boolean on)。好吧,我
這么調(diào)用
setSpeakerphoneOn(true),看看實現(xiàn)。
這次我沒再浪費(fèi)時間了,我用一個新的工具coolfind,把搜索framework目錄,尋找*.java文件,匹配字符串setSpeakerphone。終于,我在
- framework/base/media/java/android/media/AudioService.java中找到了。
- public void setSpeakerphoneOn(boolean on){
- if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
- return;
- }
- if (on) {
//看到這里,是不是明白十之八九了?下面這個調(diào)用是:
//強(qiáng)制通話使用speaker!原來是這么個意思!
- AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION,
- ioSystem.FORCE_SPEAKER);
- mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
- } else {
- AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION,
- ioSystem.FORCE_NONE);
- mForcedUseForComm = AudioSystem.FORCE_NONE;
- }
- }
好了,說點題外話,既然Android源碼都放開給我們了,有什么理由我們不去多搜搜呢?上網(wǎng)google也是搜,查源代碼也是一樣嗎。不過我們要有目的:就是找到一個合適的使用場景。
force_use和force_config就不用我再解釋了吧?
- [--->AudioPolicyManagerBase::AudioPolicyManagerBase]
- ...
//下面這個意思就是把幾種for_use的情況使用的設(shè)備全部置為NONE。
//比如設(shè)置FOR_MEDIA的場景,使用的設(shè)備就是FORCE_NONE
- for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
- mForceUse[i] = AudioSystem::FORCE_NONE;
- }
// 目前可以的輸出設(shè)備,耳機(jī)和外放
- mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
- AudioSystem::DEVICE_OUT_SPEAKER;
- //目前可用的輸入設(shè)備,內(nèi)置MIC
- mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
- 又得來看看AudioSystem是怎么定義輸入輸出設(shè)備的了。
- [--->mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE]
- enum audio_devices {
- // output devices
- DEVICE_OUT_EARPIECE = 0x1,
- DEVICE_OUT_SPEAKER = 0x2,
- DEVICE_OUT_WIRED_HEADSET = 0x4,
- DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- DEVICE_OUT_AUX_DIGITAL = 0x400,
- DEVICE_OUT_DEFAULT = 0x8000,
- DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER |
- DEVICE_OUT_WIRED_HEADSET | DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_DEFAULT),
- DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
- DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
- // input devices
- DEVICE_IN_COMMUNICATION = 0x10000,
- DEVICE_IN_AMBIENT = 0x20000,
- DEVICE_IN_BUILTIN_MIC = 0x40000,
- DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
- DEVICE_IN_WIRED_HEADSET = 0x100000,
- DEVICE_IN_AUX_DIGITAL = 0x200000,
- DEVICE_IN_VOICE_CALL = 0x400000,
- DEVICE_IN_BACK_MIC = 0x800000,
- DEVICE_IN_DEFAULT = 0x80000000,
- DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT |
- DEVICE_IN_BUILTIN_MIC |DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET |
- DEVICE_IN_AUX_DIGITAL | DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC |
- DEVICE_IN_DEFAULT)
- };
一些比較容易眼花的東西我標(biāo)成紅色的了。這么多東西,不過沒什么我們不明白的了。
得嘞,繼續(xù)走。
[--->AudioPolicyManagerBase::AudioPolicyManagerBase]
// 目前可以的輸出設(shè)備,又有耳機(jī)又有外放,配置很強(qiáng)悍啊。
//注意這里是OR操作符,最終mAvailableOutputDevices = 0X3
mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
AudioSystem::DEVICE_OUT_SPEAKER;
//目前可用的輸入設(shè)備,內(nèi)置MIC,mAvailableInputDevices為0x4000,不過我們不關(guān)注input
mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
下面東西就很少了,我們一氣呵成。
//創(chuàng)建一個AudioOutputDescriptor,并設(shè)置它的device為外設(shè)0x2
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
//調(diào)用APS的openOutput,得到一個mHardwareOutput東東。這是個int型
//不過保不準(zhǔn)是一個指針也不一定喔。
//而且,下面的參數(shù)都是指針類型(flags除外),難道?有人會改value嗎?
- mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
//這個...估計是把int和指針加入到一個map了,方便管理。
addOutput(mHardwareOutput, outputDesc);
//不知道干嘛,待會看。
setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
//不知道干嘛,待會看。
updateDeviceForStrategy();
好了,上面還有一系列函數(shù),等著我們調(diào)用呢。我們一個一個看。
提前說一下,這塊可是AudioManagerBase的核心喔。
[---->AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor()]
AudioOutputDescriptor是個什么?我不是神,我也得看注釋。
// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
明白了么?大概意思就是它,是這么一個東西:
l 描述audio輸出的,可以用來保存一些配置信息。
l 跟蹤音頻stream類型使用這個output的一些情況。
沒明白吧?以后碰到場景就明白了。
它的構(gòu)造函數(shù)干了如下勾當(dāng):
- AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
- : mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
- mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0)
- {}
//很好,統(tǒng)統(tǒng)都置零了。上面這些東西不用我解釋了吧?命名規(guī)則也可以看出來。
OK,go on.
[--->mHardwareOutput = mpClientInterface->openOutput()]:
這里調(diào)用的是APS的openOutput,看看去:
- [--->AudioPolicyService::openOutput]
- audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- AudioSystem::output_flags flags)
- {
- sp
af = AudioSystem::get_audio_flinger(); - //娘希匹,搞到AF去了
- return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels,
- pLatencyMs, flags);
- }
- [----->AudioFlinger::openOutput]
- int AudioFlinger::openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- uint32_t flags)
- {
- //我們思考下傳進(jìn)來的值吧
- //*pDevices=0x2,代表外放
- //其他都是0。 嘿嘿,有了值,這不就知道下面該怎么走了嗎?
- status_t status;
- PlaybackThread *thread = NULL;
- mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
- uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
- uint32_t format = pFormat ? *pFormat : 0;
- uint32_t channels = pChannels ? *pChannels : 0;
- uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
- Mutex::Autolock _l(mLock);
- //HAL對象得到一個AudioStreamOut,傳進(jìn)去的值會改嗎?
- AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
- &status);
- mHardwareStatus = AUDIO_HW_IDLE;
- if (output != 0) {
#p#
//走哪個分支?我把答案告訴大家吧。
//剛才那個mAudioHardware->openOutputStream確實會更改指針對應(yīng)的value。
//當(dāng)然,我們說了,AF使用的是GENERIC的Audio硬件。大家有興趣可以去看看它的實現(xiàn)。
//我待會再貼出它的內(nèi)容。反正到這里。
//那幾個值變成:format為PCM_16_BIT,channels為2,samplingRate為44100
//這樣的話,那只能走else分支了。
- if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
- (format != AudioSystem::PCM_16_BIT) ||
- (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
- thread = new DirectOutputThread(this, output, ++mNextThreadId);
- } else {
//還記得前兩節(jié)分析的同學(xué),看到這里是不是明白了?恩,原來
//open一個Output,就會在AF中創(chuàng)建一個混音線程。設(shè)計得真好。
//想象下,所有設(shè)置為外放的程序,它的輸出都是這個外放stream混音線程來工作
//所有設(shè)置為耳機(jī)的程序,它的輸出都是這個耳機(jī)stream混音線程來完成。
//為什么對stream特加強(qiáng)調(diào)呢,沒看見
//我們調(diào)用的是mAudioHardware->openOutputStream(0x2,,,)嘛。返回的
//是一個AudioStreamOut,可不是設(shè)備喔。Android把這些個東西都交給HAL層去實現(xiàn)了。
//不用自己來管理系統(tǒng)上有什么耳機(jī),外設(shè),藍(lán)牙真實設(shè)備之類的東東,它反正用AudioStreamOut來表示它想要的就可以了。例如Generic的Audio Hal只支持一個OutputStream。--> only my opinion
thread = new MixerThread(this, output, ++mNextThreadId);
}
//好了,又多得了一個線程,
- mPlaybackThreads.add(mNextThreadId, thread);
- if (pSamplingRate) *pSamplingRate = samplingRate;
- if (pFormat) *pFormat = format;
- if (pChannels) *pChannels = channels;
- if (pLatencyMs) *pLatencyMs = thread->latency();
//從這里返回的是混音線程的索引。
return mNextThreadId;
return 0;//如果沒創(chuàng)建成功線程,則返回零。
}
好,我們回到AudioManagerBase中。
- [--->AudioPolicyManagerBase::AudioPolicyManagerBase]
- mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
//上面實際就返回一個線程index。我有點疑惑,難道APS就只這么一個實際是線程index的東西就就行了嗎?雖然它把這個index當(dāng)成hardware的標(biāo)識了。
//這個...估計是把int和指針加入到一個map了,方便管理。不看了。
addOutput(mHardwareOutput, outputDesc);
//不知道干嘛,待會看。
- setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
- [--->setOutputDevice(mHardwareOutput,...)]
這個函數(shù),很重要!另外,再傳點技巧。不要老在source insight中后退后退了,直接找到window菜單,里邊列出了最近打開的文件,找到我們的AudioManagerBase.cpp,不就行了嗎?
void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)
{
//注意我們的參數(shù):
// output = 1,
//device為AudioSystem::DEVICE_OUT_SPEAKER
// force為true,delayMs用默認(rèn)值0
//map吧?剛才通過addOutput已經(jīng)加進(jìn)去了
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
- if (outputDesc->isDuplicated()) {
- setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
- setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
- return;
- }
//還記得addOutput前設(shè)置的device嗎?對了,為0X3,外放|耳機(jī)
- uint32_t prevDevice = (uint32_t)outputDesc->device();
- 現(xiàn)在設(shè)置的是外設(shè),
- if ((device == 0 || device == prevDevice) && !force) {
- return;
- }
- //喔,設(shè)置這個outputDesc為外放
- outputDesc->mDevice = device;
- popCount為2,因為device=0x2=0010
//另外,我對下面這個output== mHardwareOutput尤其感興趣。還記得我們剛才的疑問嗎?
// mHardwareOutput實際上是AF返回的一個線程索引,那AMB怎么根據(jù)這樣一個東西來
//管理所有的線程呢?果然,這里就比較了output是不是等于最初創(chuàng)建的線程索引
//這就表明。雖然只有這么一個mHardwareOutput,但實際上還是能夠操作其他output的!
- if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {
- setStrategyMute(STRATEGY_MEDIA, true, output);
- usleep(outputDesc->mLatency*2*1000);
- }
// 暈,又冒出來一個AudioParameter,不過意思卻很明白
//說我們要設(shè)置路由,新的輸出設(shè)備為外放
//等我們以后講由外放切換到耳機(jī),再來看這個問題。
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)device);
- mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs);
- // update stream volumes according to new device
- applyStreamVolumes(output, device, delayMs);
// if changing from a combined headset + speaker route, unmute media streams
if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) {
//這里說,把media的音量置為0。以后再說。
setStrategyMute(STRATEGY_MEDIA, false, output, delayMs);
}
}
好了,返回了。
setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
這個調(diào)研,更新了mHardwareOutput對應(yīng)的輸出路由設(shè)備,而且還發(fā)了一個命令給APS,說你給我更新對應(yīng)混音線程的輸出路由設(shè)備。
- [--->AudioPolicyManagerBase::AudioPolicyManagerBase]
- .....
- addOutput(mHardwareOutput, outputDesc);
- setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER,
- true);
//只剩下最后一個函數(shù)了
- updateDeviceForStrategy();
- [----->updateDeviceForStrategy()]
- void AudioPolicyManagerBase::updateDeviceForStrategy()
- {
- for (int i = 0; i < NUM_STRATEGIES; i++) {
- mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);
- }
- }
暈,又出來一個枚舉。我們看看
- [---->for (int i = 0; i < NUM_STRATEGIES; i++)]
- NUM_STRATEGIES在hardware/libhardware_legacy/include/hardware_legacy/
- AudioPolicyManagerBase.h中定義。
- enum routing_strategy {
- //好像很好理解
- STRATEGY_MEDIA,
- STRATEGY_PHONE,//通話音嗎?
- STRATEGY_SONIFICATION,//除了其他三個外的,可以是鈴聲,提醒聲等。
- STRATEGY_DTMF,//好像是撥號音
- NUM_STRATEGIES
- };
這個,反正我在SDK上沒找到對應(yīng)說明,我們待到以后看看會不會柳暗花明呢?
[----->getDeviceForStrategy((routing_strategy)i, false)]
看這個函數(shù)名的意思是,為各種策略找到它對應(yīng)的設(shè)備。
uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
{
// fromCache為false
//放眼望去,這個函數(shù)好像涉及到很對策略方面的事情。
//我們大概講解下,至于系統(tǒng)為什么要這么做,問Google吧。
- uint32_t device = 0;
- switch (strategy) {
- case STRATEGY_DTMF:
- if (mPhoneState != AudioSystem::MODE_IN_CALL) {
- //如果在打電話過程中,你再按按鍵,則和MEDIA走一個設(shè)備
- device = getDeviceForStrategy(STRATEGY_MEDIA, false);
- break;
- }
//注意這里沒有break,所以在其他mode下,DTMF和PHONE用一個策略
case STRATEGY_PHONE:
//還得判斷用戶是不是強(qiáng)制使用了輸出設(shè)備。
- switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
- case AudioSystem::FORCE_BT_SCO:
- if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
- device = mAvailableOutputDevices &
- AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- if (device) break;
- }
- device = mAvailableOutputDevices &
- AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
- if (device) break;
- // if SCO device is requested but no SCO device is available, fall back to default
- // case&n
當(dāng)前文章:Android深入淺出之Audio第三部分AudioPolicy
文章源于:http://fisionsoft.com.cn/article/dhghjcc.html


咨詢
建站咨詢
