Android深入浅出之Audio第三部分Audio Policy

移动开发 Android
上回我们说了AudioFlinger(AF),总感觉代码里边有好多东西没说清楚,心里发毛。就看了看AF的流程,我们敢说自己深入了解了Android系统吗?AudioPolicyService(APS)是个什么东西?为什么要有它的存在?下层的Audio HAL层又是怎么结合到Android中来的?

一 目的

上回我们说了AudioFlinger(AF),总感觉代码里边有好多东西没说清楚,心里发毛。就看了看AF的流程,我们敢说自己深入了解了Android系统吗?AudioPolicyService(APS)是个什么东西?为什么要有它的存在?下层的Audio HAL层又是怎么结合到Android中来的?更有甚者,问个实在问题:插入耳机后,声音又怎么从最开始的外放变成从耳机输出了?调节音量的时候到底是调节Music的还是调节来电音量呢?这些东西,我们在AF的流程中统统都没讲到。但是这些他们又是至关重要的。从我个人理解来看,策略(Policy)比流程更复杂和难懂。

当然,遵循我们的传统分析习惯,得有一个切入点,否则我们都不知道从何入手了。

这里的切入点将是:

l         AF和APS系统第一次起来后,到底干了什么。

l         检测到耳机插入事件后,AF和APS的处理。

大家跟着我一步步来看,很快就发现,啊哈,APS也不是那么难嘛。

另外,这次代码分析的格式将参考《Linux内核情景分析》的样子,函数调用的解析将采用深度优先的办法,即先解释所调用的函数,然后再出来继续讲。

我曾经数度放弃分析APS,关键原因是我没找到切入点,只知道代码从头看到尾!

二 AF和APS的诞生

这个东西,已经说得太多了。在framework/base/media/MediaServer/Main_MediaServer中。

我们看看。

  1. int main(int argc, char** argv) 
  2.  
  3.  
  4.     sp<ProcessState> proc(ProcessState::self()); 
  5.  
  6.     sp<IServiceManager> sm = defaultServiceManager(); 
  7.  
  8.     //先创建AF 
  9.  
  10. AudioFlinger::instantiate(); 
  11.  
  12.     //再创建APS 
  13.  
  14. AudioPolicyService::instantiate(); 
  15.  
  16.   
  17.  
  18.     ProcessState::self()->startThreadPool(); 
  19.  
  20.     IPCThreadState::self()->joinThreadPool(); 
  21.  

2.1 new AudioFlinger

前面说过,instantiate内部会实例化一个对象,那直接看AF的构造函数。

  1. AudioFlinger::AudioFlinger() 
  2.  
  3.     : BnAudioFlinger(),//基类构造函数 
  4.  
  5.         mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0
  6.  

注意mAudioHardware和mNextThreadId

mHardwareStatus = AUDIO_HW_IDLE;

//创建audio的HAL代表

    mAudioHardware = AudioHardwareInterface::create();

mHardwareStatus = AUDIO_HW_INIT;

//下面这些不至于会使用APS吧?APS还没创建呢!

  1. if (mAudioHardware->initCheck() == NO_ERROR) { 
  2.  
  3.        setMode(AudioSystem::MODE_NORMAL); 
  4.  
  5.        setMasterVolume(1.0f); 
  6.  
  7.        setMasterMute(false); 
  8.  
  9.    } 

感觉上,AF的构造函数就是创建了一个最重要的AudioHardWare的HAL代表。

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

不过:AF创建了一个AudioHardware的HAL对象。注意整个系统就这一个AudioHardware了。也就是说,不管是线控耳机,蓝牙耳机,麦克,外放等等,最后都会由这一个HAL统一管理。

再看APS吧。

2.2 new AudioPolicyService

  1. AudioPolicyService::AudioPolicyService() 
  2.  
  3.     : BnAudioPolicyService() , mpPolicyManager(NULL) 
  4.  
  5.  
  6.   //  mpPolicyManager?策略管理器?可能很重要 
  7.  
  8. char value[PROPERTY_VALUE_MAX]; 
  9.  
  10.   
  11.  
  12.     // TonePlayback?播放铃声的?为什么放在这里?以后来看看 
  13.  
  14.     mTonePlaybackThread = new AudioCommandThread(String8("")); 
  15.  
  16. // Audio Command?音频命令?看到Command,我就想到设计模式中的Command模式了 
  17.  
  18. //Android尤其是MediaPlayerService中大量使用了这种模式。 
  19.  
  20.     mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread")); 
  21.  
  22.   
  23.  
  24. #if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST) 
  25.  
  26.  //注意AudioPolicyManagerBase的构造函数,把this传进去了。 
  27.  
  28.     mpPolicyManager = new AudioPolicyManagerBase(this); 
  29.  
  30.     //先假设我们使用Generic的Audio设备吧。 
  31.  
  32. #else 
  33.  
  34.     ... 
  35.  
  36.     
  37.  
  38. #endif 

// 根据系统属性来判断摄像机是否强制使用声音。这个...为什么会放在这里?

//手机带摄像机好像刚出来的时候,为了防止偷拍,强制按快门的时候必须发出声音

//就是这个目的吧?

  1.  property_get("ro.camera.sound.forced", value, "0"); 
  2.  
  3. mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value); 
  4.  

so easy!,不至于吧?我们不应该放过任何一个疑问!这么多疑问,先看哪个呢?这里分析的是Audio Policy,而构造函数中又创建了一个AudioPolicyManagerBase,而且不同厂商还可以实现自己的AudioPolicyManager,看来这个对于音频策略有至关重要的作用了。

不得不说的是,Android代码中的这些命名在关键地方上还是比较慎重和准确的。

另外,AudioPolicyManagerBase的构造函数可是把APS传进去了,看来又会有一些回调靠APS了。真绕。

2.3 AudioPolicyManagerBase

代码位置在framework/base/libs/audioflinger/AudioPolicyManagerBase.cpp中

  1. AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface) 
  2.  
  3.     : 
  4.  
  5.  mPhoneState(AudioSystem::MODE_NORMAL), ---->这里有电话的状态? 
  6.  
  7. mRingerMode(0), 
  8.  
  9. mMusicStopTime(0), 
  10.  
  11.  mLimitRingtoneVolume(false
  12.  
  13.  
  14. [--->mPhoneState(AudioSystem::MODE_NORMAL)] 

   AudioSystem其实是窥视Android如何管理音频系统的好地方。位置在

framework/base/include/media/AudioSystem.h中,定义了大量的枚举之类的东西来表达Google对音频系统的看法。我们只能见招拆招了。

下面是audio_mode的定义。这里要注意一个地方:

这些定义都和SDK中的JAVA层定义类似。实际上应该说先有C++层的定义,然后再反映到JAVA层中。但是C++层的定义一般没有解释说明,而SDK中有。所以我们不能不面对的一个痛苦现实就是:常常需要参考SDK的说明才能搞明白到底是什么。

关于C++的AudioSystem这块,SDK的说明在AudioManager中。

  1. enum audio_mode { 
  2.  
  3. //解释参考SDK说明,以下不再说明 
  4.  
  5.         MODE_INVALID = -2//无效mode 
  6.  
  7.         MODE_CURRENT = -1,//当前mode,和音频设备的切换(路由)有关 
  8.  
  9.         MODE_NORMAL = 0,//正常mode,没有电话和铃声 
  10.  
  11.         MODE_RINGTONE,//收到来电信号了,此时会有铃声 
  12.  
  13.         MODE_IN_CALL,//电话mode,这里表示已经建立通话了 
  14.  
  15.         NUM_MODES  // Android大量采用这种技巧来表示枚举结束了。 
  16.  
  17.     }; 

好,继续:

  1. ... 
  2.  
  3. mPhoneState(AudioSystem::MODE_NORMAL), ---->这里有电话的状态? 
  4.  
  5. mRingerMode(0), 
  6.  
  7. mMusicStopTime(0), 
  8.  
  9.  mLimitRingtoneVolume(false
  10.  
  1. mpClientInterface = clientInterface;//BT,保存APS对象。 
  2.  
  3. //forceUse?这是个什么玩意儿? 
  4.  
  5.     for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) { 
  6.  
  7.         mForceUse[i] = AudioSystem::FORCE_NONE; 
  8.  
  9.     } 

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

注意,这里有两个枚举,太无耻了。先看看FORCE_NONE这个

  1. enum forced_config {强制_配置,看名字好像是强制使用设备吧,比如外放,耳机,蓝牙等 
  2.  
  3.         FORCE_NONE, 
  4.  
  5.         FORCE_SPEAKER, 
  6.  
  7.         FORCE_HEADPHONES, 
  8.  
  9.         FORCE_BT_SCO, 
  10.  
  11.         FORCE_BT_A2DP, 
  12.  
  13.         FORCE_WIRED_ACCESSORY, 
  14.  
  15.         FORCE_BT_CAR_DOCK, 
  16.  
  17.         FORCE_BT_DESK_DOCK, 
  18.  
  19.         NUM_FORCE_CONFIG, 
  20.  
  21.         FORCE_DEFAULT = FORCE_NONE //这个,太无聊了。 
  22.  
  23. }; 

再看看AudioSystem::NUM_FORCE_USE这个

  1. enum force_use { 
  2.  
  3.         FOR_COMMUNICATION,//这里是for_xxx,不是force_xxx。 
  4.  
  5.         FOR_MEDIA, 
  6.  
  7.         FOR_RECORD, 
  8.  
  9.         FOR_DOCK, 
  10.  
  11.         NUM_FORCE_USE 
  12.  
  13.     }; 

不懂,两个都不懂。为何?能猜出来什么吗?也不行。因为我们没找到合适的场景!那好吧,我们去SDK找找。恩

我看到AudioManager这个函数setSpeakerphoneOn (boolean on)。好吧,我

这么调用

setSpeakerphoneOn(true),看看实现。

这次我没再浪费时间了,我用一个新的工具coolfind,把搜索framework目录,寻找*.java文件,匹配字符串setSpeakerphone。终于,我在

  1. framework/base/media/java/android/media/AudioService.java中找到了。 
  2.  
  3. public void setSpeakerphoneOn(boolean on){ 
  4.  
  5.         if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) { 
  6.  
  7.             return
  8.  
  9.         } 
  10.  
  11.         if (on) { 

//看到这里,是不是明白十之八九了?下面这个调用是:

//强制通话使用speaker!原来是这么个意思!

        

  1. AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, 
  2.  
  3. ioSystem.FORCE_SPEAKER); 
  4.  
  5.          mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 
  6.  
  7.      } else { 
  8.  
  9.          AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, 
  10.  
  11. ioSystem.FORCE_NONE); 
  12.  
  13.          mForcedUseForComm = AudioSystem.FORCE_NONE; 
  14.  
  15.      } 
  16.  
  17.  } 

好了,说点题外话,既然Android源码都放开给我们了,有什么理由我们不去多搜搜呢?上网google也是搜,查源代码也是一样吗。不过我们要有目的:就是找到一个合适的使用场景。

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

  1. [--->AudioPolicyManagerBase::AudioPolicyManagerBase] 
  2.  
  3. ... 

//下面这个意思就是把几种for_use的情况使用的设备全部置为NONE。

//比如设置FOR_MEDIA的场景,使用的设备就是FORCE_NONE

  1. for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) { 
  2.  
  3.         mForceUse[i] = AudioSystem::FORCE_NONE; 
  4.  
  5.     } 

  // 目前可以的输出设备,耳机和外放

  1.  mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE | 
  2.  
  3.                         AudioSystem::DEVICE_OUT_SPEAKER; 
  4.  
  5. //目前可用的输入设备,内置MIC 
  6.  
  7.     mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC; 
  8.  
  9. 又得来看看AudioSystem是怎么定义输入输出设备的了。 
  10.  
  11. [--->mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE] 
  12.  
  13. enum audio_devices { 
  14.  
  15.         // output devices 
  16.  
  17.         DEVICE_OUT_EARPIECE = 0x1
  18.  
  19.         DEVICE_OUT_SPEAKER = 0x2
  20.  
  21.         DEVICE_OUT_WIRED_HEADSET = 0x4
  22.  
  23.         DEVICE_OUT_WIRED_HEADPHONE = 0x8
  24.  
  25.         DEVICE_OUT_BLUETOOTH_SCO = 0x10
  26.  
  27.         DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20
  28.  
  29.         DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40
  30.  
  31.         DEVICE_OUT_BLUETOOTH_A2DP = 0x80
  32.  
  33.         DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100
  34.  
  35.         DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200
  36.  
  37.         DEVICE_OUT_AUX_DIGITAL = 0x400
  38.  
  39.         DEVICE_OUT_DEFAULT = 0x8000
  40.  
  41.         DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | 
  42.  
  43.  DEVICE_OUT_WIRED_HEADSET | DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |DEVICE_OUT_BLUETOOTH_SCO_CARKIT | 
  44.  
  45.  DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | 
  46.  
  47.  DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_DEFAULT), 
  48.  
  49.    DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | 
  50.  
  51. DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), 
  52.  
  53.   
  54.  
  55.         // input devices 
  56.  
  57.         DEVICE_IN_COMMUNICATION = 0x10000
  58.  
  59.         DEVICE_IN_AMBIENT = 0x20000
  60.  
  61.         DEVICE_IN_BUILTIN_MIC = 0x40000
  62.  
  63.         DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000
  64.  
  65.         DEVICE_IN_WIRED_HEADSET = 0x100000
  66.  
  67.         DEVICE_IN_AUX_DIGITAL = 0x200000
  68.  
  69.         DEVICE_IN_VOICE_CALL = 0x400000
  70.  
  71.         DEVICE_IN_BACK_MIC = 0x800000
  72.  
  73.         DEVICE_IN_DEFAULT = 0x80000000
  74.  
  75.         DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | 
  76.  
  77. DEVICE_IN_BUILTIN_MIC |DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | 
  78.  
  79.   DEVICE_IN_AUX_DIGITAL | DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC | 
  80.  
  81. DEVICE_IN_DEFAULT) 
  82.  
  83.     }; 

一些比较容易眼花的东西我标成红色的了。这么多东西,不过没什么我们不明白的了。

得嘞,继续走。

[--->AudioPolicyManagerBase::AudioPolicyManagerBase]

// 目前可以的输出设备,又有耳机又有外放,配置很强悍啊。

//注意这里是OR操作符,最终mAvailableOutputDevices = 0X3

    mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |

                        AudioSystem::DEVICE_OUT_SPEAKER;

//目前可用的输入设备,内置MIC,mAvailableInputDevices为0x4000,不过我们不关注input

 mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;

下面东西就很少了,我们一气呵成。

//创建一个AudioOutputDescriptor,并设置它的device为外设0x2

  1. AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); 
  2.  
  3. outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER; 

//调用APS的openOutput,得到一个mHardwareOutput东东。这是个int型

//不过保不准是一个指针也不一定喔。

//而且,下面的参数都是指针类型(flags除外),难道?有人会改value吗?

  1. mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice, 
  2.  
  3.                                     &outputDesc->mSamplingRate, 
  4.  
  5.                                     &outputDesc->mFormat, 
  6.  
  7.                                     &outputDesc->mChannels, 
  8.  
  9.                                     &outputDesc->mLatency, 
  10.  
  11.                                     outputDesc->mFlags); 

//这个...估计是把int和指针加入到一个map了,方便管理。

addOutput(mHardwareOutput, outputDesc);

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

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

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

    updateDeviceForStrategy();

好了,上面还有一系列函数,等着我们调用呢。我们一个一个看。

提前说一下,这块可是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的一些情况。

没明白吧?以后碰到场景就明白了。

它的构造函数干了如下勾当:

  1. AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor() 
  2.  
  3.     : mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0), 
  4.  
  5.     mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0
  6.  
  7. {} 

//很好,统统都置零了。上面这些东西不用我解释了吧?命名规则也可以看出来。

OK,go on.

[--->mHardwareOutput = mpClientInterface->openOutput()]:

这里调用的是APS的openOutput,看看去:

  1. [--->AudioPolicyService::openOutput] 
  2.  
  3. audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices, 
  4.  
  5.                                 uint32_t *pSamplingRate, 
  6.  
  7.                                 uint32_t *pFormat, 
  8.  
  9.                                 uint32_t *pChannels, 
  10.  
  11.                                 uint32_t *pLatencyMs, 
  12.  
  13.                                 AudioSystem::output_flags flags) 
  14.  
  15.  
  16. sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 
  17.  
  18. //娘希匹,搞到AF去了 
  19.  
  20. return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, 
  21.  
  22.  pLatencyMs, flags); 
  23.  
  24.  
  25. [----->AudioFlinger::openOutput] 
  26.  
  27. int AudioFlinger::openOutput(uint32_t *pDevices, 
  28.  
  29.                                 uint32_t *pSamplingRate, 
  30.  
  31.                                 uint32_t *pFormat, 
  32.  
  33.                                 uint32_t *pChannels, 
  34.  
  35.                                 uint32_t *pLatencyMs, 
  36.  
  37.                                 uint32_t flags) 
  38.  
  39.  
  40. //我们思考下传进来的值吧 
  41.  
  42. //*pDevices=0x2,代表外放 
  43.  
  44. //其他都是0。 嘿嘿,有了值,这不就知道下面该怎么走了吗? 
  45.  
  46.     status_t status; 
  47.  
  48.     PlaybackThread *thread = NULL; 
  49.  
  50.     mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; 
  51.  
  52.     uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0
  53.  
  54.     uint32_t format = pFormat ? *pFormat : 0
  55.  
  56.     uint32_t channels = pChannels ? *pChannels : 0
  57.  
  58.     uint32_t latency = pLatencyMs ? *pLatencyMs : 0
  59.  
  60.   
  61.  
  62.      Mutex::Autolock _l(mLock); 
  63.  
  64. //HAL对象得到一个AudioStreamOut,传进去的值会改吗? 
  65.  
  66.     AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices, 
  67.  
  68.                                                              (int *)&format, 
  69.  
  70.                                                              &channels, 
  71.  
  72.                                                              &samplingRate, 
  73.  
  74.                                                              &status); 
  75.  
  76.       mHardwareStatus = AUDIO_HW_IDLE; 
  77.  
  78.   
  79.  
  80. if (output != 0) { 

#p#

//走哪个分支?我把答案告诉大家吧。

//刚才那个mAudioHardware->openOutputStream确实会更改指针对应的value。

//当然,我们说了,AF使用的是GENERIC的Audio硬件。大家有兴趣可以去看看它的实现。

//我待会再贴出它的内容。反正到这里。

//那几个值变成:format为PCM_16_BIT,channels为2,samplingRate为44100

//这样的话,那只能走else分支了。

      

  1. if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || 
  2.  
  3.            (format != AudioSystem::PCM_16_BIT) || 
  4.  
  5.            (channels != AudioSystem::CHANNEL_OUT_STEREO)) { 
  6.  
  7.            thread = new DirectOutputThread(this, output, ++mNextThreadId); 
  8.  
  9.           } else { 

//还记得前两节分析的同学,看到这里是不是明白了?恩,原来

//open一个Output,就会在AF中创建一个混音线程。设计得真好。

//想象下,所有设置为外放的程序,它的输出都是这个外放stream混音线程来工作

//所有设置为耳机的程序,它的输出都是这个耳机stream混音线程来完成。

//为什么对stream特加强调呢,没看见

//我们调用的是mAudioHardware->openOutputStream(0x2,,,)嘛。返回的

//是一个AudioStreamOut,可不是设备喔。Android把这些个东西都交给HAL层去实现了。

//不用自己来管理系统上有什么耳机,外设,蓝牙真实设备之类的东东,它反正用AudioStreamOut来表示它想要的就可以了。例如Generic的Audio Hal只支持一个OutputStream。--> only my opinion

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

  }

//好了,又多得了一个线程,

  1. mPlaybackThreads.add(mNextThreadId, thread); 
  2.  
  3.       if (pSamplingRate) *pSamplingRate = samplingRate; 
  4.  
  5.       if (pFormat) *pFormat = format; 
  6.  
  7.       if (pChannels) *pChannels = channels; 
  8.  
  9.       if (pLatencyMs) *pLatencyMs = thread->latency(); 

//从这里返回的是混音线程的索引。

        return mNextThreadId;

    return 0;//如果没创建成功线程,则返回零。

}

好,我们回到AudioManagerBase中。

  1. [--->AudioPolicyManagerBase::AudioPolicyManagerBase] 
  2.  
  3. mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice, 
  4.  
  5.                                     &outputDesc->mSamplingRate, 
  6.  
  7.                                     &outputDesc->mFormat, 
  8.  
  9.                                     &outputDesc->mChannels, 
  10.  
  11.                                     &outputDesc->mLatency, 
  12.  
  13.                                     outputDesc->mFlags); 

//上面实际就返回一个线程index。我有点疑惑,难道APS就只这么一个实际是线程index的东西就就行了吗?虽然它把这个index当成hardware的标识了。

  //这个...估计是把int和指针加入到一个map了,方便管理。不看了。

addOutput(mHardwareOutput, outputDesc);

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

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

这个函数,很重要!另外,再传点技巧。不要老在source insight中后退后退了,直接找到window菜单,里边列出了最近打开的文件,找到我们的AudioManagerBase.cpp,不就行了吗?

void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)

{

//注意我们的参数:

// output = 1,

//device为AudioSystem::DEVICE_OUT_SPEAKER

// force为true,delayMs用默认值0

//map吧?刚才通过addOutput已经加进去了

  1. AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); 
  2.  
  3.   
  4.  
  5.     if (outputDesc->isDuplicated()) { 
  6.  
  7.         setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs); 
  8.  
  9.         setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs); 
  10.  
  11.         return
  12.  

//还记得addOutput前设置的device吗?对了,为0X3,外放|耳机

  1. uint32_t prevDevice = (uint32_t)outputDesc->device(); 
  2.  
  3. 现在设置的是外设, 
  4.  
  5.     if ((device == 0 || device == prevDevice) && !force) { 
  6.  
  7.         return
  8.  
  9.     } 
  10.  
  11. //喔,设置这个outputDesc为外放 
  12.  
  13.     outputDesc->mDevice = device; 
  14.  
  15. popCount为2,因为device=0x2=0010 

//另外,我对下面这个output== mHardwareOutput尤其感兴趣。还记得我们刚才的疑问吗?

// mHardwareOutput实际上是AF返回的一个线程索引,那AMB怎么根据这样一个东西来

//管理所有的线程呢?果然,这里就比较了output是不是等于最初创建的线程索引

//这就表明。虽然只有这么一个mHardwareOutput,但实际上还是能够操作其他output的!

  1.   if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) { 
  2.  
  3.       setStrategyMute(STRATEGY_MEDIA, true, output); 
  4.  
  5. usleep(outputDesc->mLatency*2*1000); 
  6.  
  7.   } 

// 晕,又冒出来一个AudioParameter,不过意思却很明白

//说我们要设置路由,新的输出设备为外放

//等我们以后讲由外放切换到耳机,再来看这个问题。

  1. AudioParameter param = AudioParameter(); 
  2.  
  3.     param.addInt(String8(AudioParameter::keyRouting), (int)device); 
  4.  
  5.     mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs); 
  6.  
  7.     // update stream volumes according to new device 
  8.  
  9.     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);

这个调研,更新了mHardwareOutput对应的输出路由设备,而且还发了一个命令给APS,说你给我更新对应混音线程的输出路由设备。

  1. [--->AudioPolicyManagerBase::AudioPolicyManagerBase] 
  2.  
  3.     .....    
  4.  
  5. addOutput(mHardwareOutput, outputDesc); 
  6.  
  7.         setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, 
  8.  
  9. true); 

  //只剩下最后一个函数了

  1. updateDeviceForStrategy(); 
  2.  
  3. [----->updateDeviceForStrategy()] 
  4.  
  5.   void AudioPolicyManagerBase::updateDeviceForStrategy() 
  6.  
  7.  
  8.     for (int i = 0; i < NUM_STRATEGIES; i++) { 
  9.  
  10.         mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false); 
  11.  
  12.     } 
  13.  

晕,又出来一个枚举。我们看看

  1. [---->for (int i = 0; i < NUM_STRATEGIES; i++)] 
  2.  
  3. NUM_STRATEGIES在hardware/libhardware_legacy/include/hardware_legacy/ 
  4.  
  5. AudioPolicyManagerBase.h中定义。 
  6.  
  7. enum routing_strategy { 
  8.  
  9. //好像很好理解 
  10.  
  11.             STRATEGY_MEDIA, 
  12.  
  13.             STRATEGY_PHONE,//通话音吗? 
  14.  
  15.             STRATEGY_SONIFICATION,//除了其他三个外的,可以是铃声,提醒声等。 
  16.  
  17.             STRATEGY_DTMF,//好像是拨号音 
  18.  
  19.             NUM_STRATEGIES 
  20.  
  21.         }; 

这个,反正我在SDK上没找到对应说明,我们待到以后看看会不会柳暗花明呢?

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

看这个函数名的意思是,为各种策略找到它对应的设备。

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

{

  //  fromCache为false

//放眼望去,这个函数好像涉及到很对策略方面的事情。

//我们大概讲解下,至于系统为什么要这么做,问Google吧。

  1. uint32_t device = 0
  2.  
  3.   
  4.  
  5.     switch (strategy) { 
  6.  
  7.     case STRATEGY_DTMF: 
  8.  
  9.         if (mPhoneState != AudioSystem::MODE_IN_CALL) { 
  10.  
  11.             //如果在打电话过程中,你再按按键,则和MEDIA走一个设备 
  12.  
  13.             device = getDeviceForStrategy(STRATEGY_MEDIA, false); 
  14.  
  15.             break
  16.  
  17.         } 

        //注意这里没有break,所以在其他mode下,DTMF和PHONE用一个策略

    case STRATEGY_PHONE:

       //还得判断用户是不是强制使用了输出设备。

  1.   switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { 
  2.  
  3.         case AudioSystem::FORCE_BT_SCO: 
  4.  
  5.             if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) { 
  6.  
  7.                 device = mAvailableOutputDevices & 
  8.  
  9.  AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 
  10.  
  11.                 if (device) break
  12.  
  13.             } 
  14.  
  15.             device = mAvailableOutputDevices & 
  16.  
  17. AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 
  18.  
  19.             if (device) break
  20.  
  21.             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO; 
  22.  
  23.             if (device) break
  24.  
  25.             // if SCO device is requested but no SCO device is available, fall back to default 
  26.  
  27. // case 
  28.  
  29.             // FALL THROUGH 
  30.  
  31.        //我们还记得强制设置那里吗?对了,此时都是FORCE_NONE 
  32.  
  33.       //而且,mAvailableOutputDevices是0X3 (外放|耳机) 
  34.  
  35.         default:    // FORCE_NONE 
  36.  
  37.             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; 
  38.  
  39.             if (device) break
  40.  
  41.             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; 
  42.  
  43.             if (device) break
  44.  
  45.    //看,下面这句会成立。啥意思?如果有耳机的话,那么输出设备就是耳机 
  46.  
  47. //太正确了。实际手机是不是就是这样的呢? 
  48.  
  49.             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE; 
  50.  
  51.             break
  52.  
  53.      //再验证下我们刚才说的,如果强制使用外放的话, 
  54.  
  55.         case AudioSystem::FORCE_SPEAKER: 
  56.  
  57.             if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) { 
  58.  
  59.                 device = mAvailableOutputDevices & 
  60.  
  61.  AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 
  62.  
  63.                 if (device) break
  64.  
  65.             } 
  66.  
  67. //果然,会强制使用外放。 
  68.  
  69.            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; 
  70.  
  71.             break
  72.  
  73.         } 
  74.  
  75.     break
  76.  
  77.     case STRATEGY_SONIFICATION://分析方法同上,我不说了。 
  78.  
  79.         if (mPhoneState == AudioSystem::MODE_IN_CALL) { 
  80.  
  81.             device = getDeviceForStrategy(STRATEGY_PHONE, false); 
  82.  
  83.             break
  84.  
  85.         } 
  86.  
  87.         device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; 
  88.  
  89. // 同样没有break,说明SONIFICATION受MEDIA策略影响。 
  90.  
  91.     case STRATEGY_MEDIA: { 
  92.  
  93.         uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL; 
  94.  
  95.         if (device2 == 0) { 
  96.  
  97.             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; 
  98.  
  99.         } 
  100.  
  101.         if (device2 == 0) { 
  102.  
  103.             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; 
  104.  
  105.         } 
  106.  
  107.    //可惜,上面那些高级设备我们都没有 
  108.  
  109.         if (device2 == 0) { 
  110.  
  111.             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; 
  112.  
  113.         } 
  114.  
  115.   //假设我们没有从SONIFICATION下来,那么device最终会= DEVICE_OUT_SPEAKER。 
  116.  
  117. //假设我们从SONIFICATION下来,那么device还是等于DEVICE_OUT_SPEAKER 
  118.  
  119. //奇怪,如果有耳机的话为何会走外放呢?普通耳机和线控耳机还能区分? 
  120.  
  121.         device |= device2; 
  122.  
  123.         } break
  124.  
  125.   
  126.  
  127.     default
  128.  
  129.         break
  130.  
  131.     } 
  132.  
  133.     return device; 
  134.  

好了,回到

  1. [---->AudioPolicyManagerBase::updateDeviceForStrategy()] 
  2.  
  3. void AudioPolicyManagerBase::updateDeviceForStrategy() 
  4.  
  5.  
  6.     for (int i = 0; i < NUM_STRATEGIES; i++) { 
  7.  
  8.         mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false); 
  9.  
  10.     } 
  11.  

这个函数完了,表明各种策略下使用的对应设备也准备好了。

真爽,一路回去,APS的构造就完了。

留个纪念:

  1. AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface) 
  2.  
  3.  
  4.   .... 
  5.  
  6. updateDeviceForStrategy(); 
  7.  
  8.  
  9. AudioPolicyService::AudioPolicyService() 
  10.  
  11. : BnAudioPolicyService() , mpPolicyManager(NULL) 
  12.  
  13.  
  14.   #if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST) 
  15.  
  16.     mpPolicyManager = new AudioPolicyManagerBase(this); 
  17.  
  18. LOGV("build for GENERIC_AUDIO - using generic audio policy"); 
  19.  
  20.  ... 
  21.  
  22. #endif 
  23.  
  24. property_get("ro.camera.sound.forced", value, "0"); 
  25.  
  26. mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value); 
  27.  

2.4总结

总结下吧,AF,APS都创建完了,得到什么了吗?下面按先后顺序说说。

l         AF创建了一个代表HAL对象的东西

l         APS创建了两个AudioCommandThread,一个用来处理命令,一个用来播放tone。我们还没看。

l         APS同时会创建AudioManagerBase,做为系统默认的音频管理

l         AMB集中管理了策略上面的事情,同时会在AF的openOutput中创建一个混音线程。同时,AMB会更新一些策略上的安排。

另外,我们分析的AMB是Generic的,但不同厂商可以实现自己的策略。例如我可以设置只要有耳机,所有类型声音都从耳机出。

上面关于AMB方面,我们还只是看了看它的代码,还没有一个实际例子来体会。

责任编辑:张叶青 来源: 博客园
相关推荐

2013-11-14 16:18:05

AndroidAudioAudioTrack

2009-06-09 15:21:39

Javascript表单验证

2013-12-13 13:41:12

2015-06-17 11:36:03

数据中心模块化

2013-11-14 15:53:53

AndroidAudioAudioFlinge

2012-02-07 15:09:03

Android核心组件Service

2009-11-18 13:30:37

Oracle Sequ

2009-11-17 17:31:58

Oracle COMM

2021-03-16 08:54:35

AQSAbstractQueJava

2011-07-04 10:39:57

Web

2010-05-06 11:34:49

实现负载均衡

2011-05-05 14:44:43

SurfaceFlinSurfaceActivity

2017-07-02 18:04:53

块加密算法AES算法

2012-05-21 10:06:26

FrameworkCocoa

2019-01-07 15:29:07

HadoopYarn架构调度器

2021-07-20 15:20:02

FlatBuffers阿里云Java

2022-09-26 09:01:15

语言数据JavaScript

2013-09-16 09:56:29

TCP协议网络协议send

2012-02-07 14:37:01

Android核心组件Service

2022-01-13 09:38:25

Android架构设计
点赞
收藏

51CTO技术栈公众号