真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何分析Android中的AudioPolicyService

如何分析Android中的AudioPolicyService,針對這個(gè)問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。

成都創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括北塔網(wǎng)站建設(shè)、北塔網(wǎng)站制作、北塔網(wǎng)頁制作以及北塔網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,北塔網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到北塔省份的部分城市,未來相信會繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

一 目的

AudioPolicyService(APS)是個(gè)什么東西?為什么要有它的存在?下層的Audio HAL層又是怎么結(jié)合到Android中來的?更有甚者,問個(gè)實(shí)在問題:插入耳機(jī)后,聲音又怎么從最開始的外放變成從耳機(jī)輸出了?調(diào)節(jié)音量的時(shí)候到底是調(diào)節(jié)Music的還是調(diào)節(jié)來電音量呢?這些東西,我們在AF的流程中統(tǒng)統(tǒng)都沒講到。但是這些他們又是至關(guān)重要的。從我個(gè)人理解來看,策略(Policy)比流程更復(fù)雜和難懂。

當(dāng)然,遵循我們的傳統(tǒng)分析習(xí)慣,得有一個(gè)切入點(diǎn),否則我們都不知道從何入手了。

這里的切入點(diǎn)將是:

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)鍵原因是我沒找到切入點(diǎn),只知道代碼從頭看到尾!

二 AF和APS的誕生

這個(gè)東西,已經(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)部會實(shí)例化一個(gè)對象,那直接看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)建了一個(gè)最重要的AudioHardWare的HAL代表。

其他好像是沒干什么策略上的事情。

不過:AF創(chuàng)建了一個(gè)AudioHardware的HAL對象。注意整個(gè)系統(tǒng)就這一個(gè)AudioHardware了。也就是說,不管是線控耳機(jī),藍(lán)牙耳機(jī),麥克,外放等等,最后都會由這一個(gè)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è)計(jì)模式中的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)制使用聲音。這個(gè)...為什么會放在這里?

//手機(jī)帶攝像機(jī)好像剛出來的時(shí)候,為了防止偷拍,強(qiáng)制按快門的時(shí)候必須發(fā)出聲音

//就是這個(gè)目的吧?

 property_get("ro.camera.sound.forced", value, "0");  mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);  }

so easy!,不至于吧?我們不應(yīng)該放過任何一個(gè)疑問!這么多疑問,先看哪個(gè)呢?這里分析的是Audio Policy,而構(gòu)造函數(shù)中又創(chuàng)建了一個(gè)AudioPolicyManagerBase,而且不同廠商還可以實(shí)現(xiàn)自己的AudioPolicyManager,看來這個(gè)對于音頻策略有至關(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其實(shí)是窺視Android如何管理音頻系統(tǒng)的好地方。位置在

framework/base/include/media/AudioSystem.h中,定義了大量的枚舉之類的東西來表達(dá)Google對音頻系統(tǒng)的看法。我們只能見招拆招了。

下面是audio_mode的定義。這里要注意一個(gè)地方:

這些定義都和SDK中的JAVA層定義類似。實(shí)際上應(yīng)該說先有C++層的定義,然后再反映到JAVA層中。但是C++層的定義一般沒有解釋說明,而SDK中有。所以我們不能不面對的一個(gè)痛苦現(xiàn)實(shí)就是:常常需要參考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,//收到來電信號了,此時(shí)會有鈴聲          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?這是個(gè)什么玩意兒?      for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {          mForceUse[i] = AudioSystem::FORCE_NONE;      }

[---->AudioSystem::FORCE_NONE和AudioSystem::NUM_FORCE_USE]

注意,這里有兩個(gè)枚舉,太無恥了。先看看FORCE_NONE這個(gè)

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 //這個(gè),太無聊了。  };

再看看AudioSystem::NUM_FORCE_USE這個(gè)

enum force_use {          FOR_COMMUNICATION,//這里是for_xxx,不是force_xxx。          FOR_MEDIA,          FOR_RECORD,          FOR_DOCK,          NUM_FORCE_USE      };

不懂,兩個(gè)都不懂。為何?能猜出來什么嗎?也不行。因?yàn)槲覀儧]找到合適的場景!那好吧,我們?nèi)DK找找。恩

我看到AudioManager這個(gè)函數(shù)setSpeakerphoneOn (boolean on)。好吧,我

這么調(diào)用

setSpeakerphoneOn(true),看看實(shí)現(xiàn)。

這次我沒再浪費(fèi)時(shí)間了,我用一個(gè)新的工具coolfind,把搜索framework目錄,尋找*.java文件,匹配字符串setSpeakerphone。終于,我在

framework/base/media/java/android/media/AudioService.java中找到了。  public void setSpeakerphoneOn(boolean on){          if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {              return;          }          if (on) {

//看到這里,是不是明白十之八九了?下面這個(gè)調(diào)用是:

//強(qiáng)制通話使用speaker!原來是這么個(gè)意思!

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;       }   }

好了,說點(diǎn)題外話,既然Android源碼都放開給我們了,有什么理由我們不去多搜搜呢?上網(wǎng)google也是搜,查源代碼也是一樣嗎。不過我們要有目的:就是找到一個(gè)合適的使用場景。

force_use和force_config就不用我再解釋了吧?

[--->AudioPolicyManagerBase::AudioPolicyManagerBase]  ...

//下面這個(gè)意思就是把幾種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)建一個(gè)AudioOutputDescriptor,并設(shè)置它的device為外設(shè)0x2

AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();  outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;

//調(diào)用APS的openOutput,得到一個(gè)mHardwareOutput東東。這是個(gè)int型

//不過保不準(zhǔn)是一個(gè)指針也不一定喔。

//而且,下面的參數(shù)都是指針類型(flags除外),難道?有人會改value嗎?

mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,                                      &outputDesc->mSamplingRate,                                      &outputDesc->mFormat,                                      &outputDesc->mChannels,                                      &outputDesc->mLatency,                                      outputDesc->mFlags);

//這個(gè)...估計(jì)是把int和指針加入到一個(gè)map了,方便管理。

addOutput(mHardwareOutput, outputDesc);

//不知道干嘛,待會看。

setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);

//不知道干嘛,待會看。

updateDeviceForStrategy();

好了,上面還有一系列函數(shù),等著我們調(diào)用呢。我們一個(gè)一個(gè)看。

提前說一下,這塊可是AudioManagerBase的核心喔。

[---->AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor()]

AudioOutputDescriptor是個(gè)什么?我不是神,我也得看注釋。

// 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.

明白了么?大概意思就是它,是這么一個(gè)東西:

l         描述audio輸出的,可以用來保存一些配置信息。

l         跟蹤音頻stream類型使用這個(gè)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對象得到一個(gè)AudioStreamOut,傳進(jìn)去的值會改嗎?      AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,                                                               (int *)&format,                                                               &channels,                                                               &samplingRate,                                                               &status);        mHardwareStatus = AUDIO_HW_IDLE;     if (output != 0) {

//走哪個(gè)分支?我把答案告訴大家吧。

//剛才那個(gè)mAudioHardware->openOutputStream確實(shí)會更改指針對應(yīng)的value。

//當(dāng)然,我們說了,AF使用的是GENERIC的Audio硬件。大家有興趣可以去看看它的實(shí)現(xiàn)。

//我待會再貼出它的內(nèi)容。反正到這里。

//那幾個(gè)值變成: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一個(gè)Output,就會在AF中創(chuàng)建一個(gè)混音線程。設(shè)計(jì)得真好。

//想象下,所有設(shè)置為外放的程序,它的輸出都是這個(gè)外放stream混音線程來工作

//所有設(shè)置為耳機(jī)的程序,它的輸出都是這個(gè)耳機(jī)stream混音線程來完成。

//為什么對stream特加強(qiáng)調(diào)呢,沒看見

//我們調(diào)用的是mAudioHardware->openOutputStream(0x2,,,)嘛。返回的

//是一個(gè)AudioStreamOut,可不是設(shè)備喔。Android把這些個(gè)東西都交給HAL層去實(shí)現(xiàn)了。

//不用自己來管理系統(tǒng)上有什么耳機(jī),外設(shè),藍(lán)牙真實(shí)設(shè)備之類的東東,它反正用AudioStreamOut來表示它想要的就可以了。例如Generic的Audio Hal只支持一個(gè)OutputStream。--> only my opinion

thread = new MixerThread(this, output, ++mNextThreadId);

}

//好了,又多得了一個(gè)線程,

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);

//上面實(shí)際就返回一個(gè)線程index。我有點(diǎn)疑惑,難道APS就只這么一個(gè)實(shí)際是線程index的東西就就行了嗎?雖然它把這個(gè)index當(dāng)成hardware的標(biāo)識了。

//這個(gè)...估計(jì)是把int和指針加入到一個(gè)map了,方便管理。不看了。

addOutput(mHardwareOutput, outputDesc);

//不知道干嘛,待會看。

setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);  [--->setOutputDevice(mHardwareOutput,...)]

這個(gè)函數(shù),很重要!另外,再傳點(diǎn)技巧。不要老在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è)置這個(gè)outputDesc為外放      outputDesc->mDevice = device;  popCount為2,因?yàn)閐evice=0x2=0010

//另外,我對下面這個(gè)output== mHardwareOutput尤其感興趣。還記得我們剛才的疑問嗎?

// mHardwareOutput實(shí)際上是AF返回的一個(gè)線程索引,那AMB怎么根據(jù)這樣一個(gè)東西來

//管理所有的線程呢?果然,這里就比較了output是不是等于最初創(chuàng)建的線程索引

//這就表明。雖然只有這么一個(gè)mHardwareOutput,但實(shí)際上還是能夠操作其他output的!

  if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {        setStrategyMute(STRATEGY_MEDIA, true, output);  usleep(outputDesc->mLatency*2*1000);    }

// 暈,又冒出來一個(gè)AudioParameter,不過意思卻很明白

//說我們要設(shè)置路由,新的輸出設(shè)備為外放

//等我們以后講由外放切換到耳機(jī),再來看這個(gè)問題。

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);

這個(gè)調(diào)研,更新了mHardwareOutput對應(yīng)的輸出路由設(shè)備,而且還發(fā)了一個(gè)命令給APS,說你給我更新對應(yīng)混音線程的輸出路由設(shè)備。

[--->AudioPolicyManagerBase::AudioPolicyManagerBase]      .....     addOutput(mHardwareOutput, outputDesc);          setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER,  true);

//只剩下最后一個(gè)函數(shù)了

updateDeviceForStrategy();  [----->updateDeviceForStrategy()]    void AudioPolicyManagerBase::updateDeviceForStrategy()  {      for (int i = 0; i < NUM_STRATEGIES; i++) {          mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);      }  }

暈,又出來一個(gè)枚舉。我們看看

[---->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,//除了其他三個(gè)外的,可以是鈴聲,提醒聲等。              STRATEGY_DTMF,//好像是撥號音              NUM_STRATEGIES          };

這個(gè),反正我在SDK上沒找到對應(yīng)說明,我們待到以后看看會不會柳暗花明呢?

[----->getDeviceForStrategy((routing_strategy)i, false)]

看這個(gè)函數(shù)名的意思是,為各種策略找到它對應(yīng)的設(shè)備。

uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)

{

//  fromCache為false

//放眼望去,這個(gè)函數(shù)好像涉及到很對策略方面的事情。

//我們大概講解下,至于系統(tǒng)為什么要這么做,問Google吧。

uint32_t device = 0;         switch (strategy) {      case STRATEGY_DTMF:          if (mPhoneState != AudioSystem::MODE_IN_CALL) {              //如果在打電話過程中,你再按按鍵,則和MEDIA走一個(gè)設(shè)備              device = getDeviceForStrategy(STRATEGY_MEDIA, false);              break;          }

//注意這里沒有break,所以在其他mode下,DTMF和PHONE用一個(gè)策略

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              // FALL THROUGH         //我們還記得強(qiáng)制設(shè)置那里嗎?對了,此時(shí)都是FORCE_NONE        //而且,mAvailableOutputDevices是0X3 (外放|耳機(jī))          default:    // FORCE_NONE              device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;              if (device) break;              device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;              if (device) break;     //看,下面這句會成立。啥意思?如果有耳機(jī)的話,那么輸出設(shè)備就是耳機(jī)  //太正確了。實(shí)際手機(jī)是不是就是這樣的呢?              device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;              break;       //再驗(yàn)證下我們剛才說的,如果強(qiáng)制使用外放的話,          case AudioSystem::FORCE_SPEAKER:              if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {                  device = mAvailableOutputDevices &   AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;                  if (device) break;              }  //果然,會強(qiáng)制使用外放。             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;              break;          }      break;      case STRATEGY_SONIFICATION://分析方法同上,我不說了。          if (mPhoneState == AudioSystem::MODE_IN_CALL) {              device = getDeviceForStrategy(STRATEGY_PHONE, false);              break;          }          device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;  // 同樣沒有break,說明SONIFICATION受MEDIA策略影響。      case STRATEGY_MEDIA: {          uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;          if (device2 == 0) {              device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;          }          if (device2 == 0) {              device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;          }     //可惜,上面那些高級設(shè)備我們都沒有          if (device2 == 0) {              device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;          }    //假設(shè)我們沒有從SONIFICATION下來,那么device最終會= DEVICE_OUT_SPEAKER。  //假設(shè)我們從SONIFICATION下來,那么device還是等于DEVICE_OUT_SPEAKER  //奇怪,如果有耳機(jī)的話為何會走外放呢?普通耳機(jī)和線控耳機(jī)還能區(qū)分?          device |= device2;          } break;         default:          break;      }      return device;  }

好了,回到

[---->AudioPolicyManagerBase::updateDeviceForStrategy()]  void AudioPolicyManagerBase::updateDeviceForStrategy()  {      for (int i = 0; i < NUM_STRATEGIES; i++) {          mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);      }  }

這個(gè)函數(shù)完了,表明各種策略下使用的對應(yīng)設(shè)備也準(zhǔn)備好了。

真爽,一路回去,APS的構(gòu)造就完了。

留個(gè)紀(jì)念:

AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)  {    ....  updateDeviceForStrategy();  }  AudioPolicyService::AudioPolicyService()  : BnAudioPolicyService() , mpPolicyManager(NULL)  {    #if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)      mpPolicyManager = new AudioPolicyManagerBase(this);  LOGV("build for GENERIC_AUDIO - using generic audio policy");   ...  #endif  property_get("ro.camera.sound.forced", value, "0");  mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);  }

總結(jié)下吧,AF,APS都創(chuàng)建完了,得到什么了嗎?下面按先后順序說說。

l         AF創(chuàng)建了一個(gè)代表HAL對象的東西

l         APS創(chuàng)建了兩個(gè)AudioCommandThread,一個(gè)用來處理命令,一個(gè)用來播放tone。我們還沒看。

l         APS同時(shí)會創(chuàng)建AudioManagerBase,做為系統(tǒng)默認(rèn)的音頻管理

l         AMB集中管理了策略上面的事情,同時(shí)會在AF的openOutput中創(chuàng)建一個(gè)混音線程。同時(shí),AMB會更新一些策略上的安排。

另外,我們分析的AMB是Generic的,但不同廠商可以實(shí)現(xiàn)自己的策略。例如我可以設(shè)置只要有耳機(jī),所有類型聲音都從耳機(jī)出。

關(guān)于如何分析Android中的AudioPolicyService問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。


網(wǎng)站名稱:如何分析Android中的AudioPolicyService
文章源于:http://weahome.cn/article/pcegdh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部