这是很早前写的一片文章,因为培训需要上传到这,已忘了代码是安卓几了,应该是5吧。
注意:对比最新的安卓,又添加了好多东西,我又懒得整理最新的代码,
但是大致的流程是OK的,有需要的可对比看

1. mediaserver

main_mediaserver.cpp (frameworks\av\media\mediaserver)
int main(int argc __unused, char** argv)
{
...
    if (doLog && (childPid = fork()) != 0) {
...
    } else {
....
        AudioFlinger::instantiate();
        MediaPlayerService::instantiate();
        CameraService::instantiate();
#ifdef AUDIO_LISTEN_ENABLED
        ALOGI("ListenService instantiated");
        ListenService::instantiate();
#endif
        AudioPolicyService::instantiate();
.....
    }
}

XXX::instantiate()
继承自BinderService的模板类
最终通过sm->addservice()创建服务(这里就在构造相应的类了)并添加到sm中。

static status_t publish(bool allowIsolated = false) {
    sp<IServiceManager> sm(defaultServiceManager());
    return sm->addService(
            String16(SERVICE::getServiceName()),
            new SERVICE(), allowIsolated);
}
......
static void instantiate() { publish(); }

2. AudioFlinger init

注意BnAudioFlinger继承自RefBase, IServiceManager::addService()第二个参数为强引用

AudioFlinger::instantiate(); --> ... -> AudioFlinger::AudioFlinger()
可其构造函数只是做了一些变量的初始化。
那么是就在这儿就停了还是在哪儿又继续了呢?

前面提过addService()第二个参数为强引用,所以会调用onFirstRef(), 在这里会继续初始化,看
void AudioFlinger::onFirstRef()
也没什么内容,就是对
mStandbyTimeInNsecs和mPatchPanel赋值
然后AudioFlinger初始化就完成了

3. AudioPolicyService init

接着可以继续分析AudioPolicyService::instantiate();
注意
AudioPolicyService会根据用户配置(audio_policy.conf)来指导AF加载设备接口

AudioPolicyService::AudioPolicyService()
构造函数也没做什么实质的事情。

同样APS继承自RefBase,会调用onFirstRef()

AudioPolicyService::onFirstRef()
    +--> // start tone playback thread mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
    + // start audio commands thread
    + // start output activity command thread
    + mAudioPolicyClient = new AudioPolicyClient(this);   //这里在构造里把this传给了APClient的mAudioPolicyService
    + mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);   --> new AudioPolicyManager(clientInterface)  
    + 然后new了个音效 // load audio processing modules, new AudioPolicyEffects();
    + 到此APS的onFirstRef内容也没了。

接下来自然想到的是要看new AudioPolicyManager(clientInterface)
和new AudioPolicyEffects()的构造函数里都有什么。

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
    + mForceUse[i] = AUDIO_POLICY_FORCE_NONE; //mForceUse数组的初始化
    | mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER); //默认的输出设备
    | loadAudioPolicyConfig() 以/vendor/etc /system/etc的顺序解析audio_policy.conf,没有就给个默认的
    |     +--> loadHwModules() 这个就是具体解析audio config,具体不分析了,最后加到mHwModules, mOutputProfiles, mInputProfiles
    |     +--> loadGlobalConfig()
    | initializeVolumeCurves(); //音阶曲线初始化  //这个应该在音量计算时会用到,以后再看。
    | *** 解析完laudio_policy.conf,然后通过 for 循环,遍历各个module的output/input,该打开的就打开,这个单独列出来 ***
    + 后面好像也没什么事情做了。

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)里对各模块的遍历是个重点,好多事情都在这里面发生。
下面只以primary的module为例分析
注意刚才的loadHwModule()是APM的,下面也有个loadHwModule(),
不过却是通过client, 最终调到的AF的loadHwModule(), 这两个不要混淆了。
从功能上来说APM::loadHwModule()是解析audio_policy.conf文件,
AF::loadHwModule()的主要为加载HAL对应的lib库并做相应的初始化

mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
      ^         +--> mpClientInterface 是APS第一次引用是传下来的那个,以AudioPolicyClientImpl.cpp为中转
      +             +-->... af->loadHwModule(name);
      +                 +-->....反正经过什么binder到了AudioFlinger::loadHwModule()
      +                     +--> settingsAllowed() 权限检查
      +------------------<--+ 返回loadHwModule_l(name) 这里是audio_module_handle_t类型
                            |     +--> AudioFlinger::loadHwModule_l()
                            |          +--> 已经加载过,返回已加载的记录mAudioHwDevs.keyAt(i)
                            |          +    load_audio_interface(name, &dev)
                            |          |        +--> hw_get_module_by_class() 谷歌搞出来的东西,具体不说了,反正就是根据传的ID加载应对的libxxx.so,注意这里已经属于AHAL范围了
                            |          |        |    audio_hw_device_open()
                            |          |        |        +--> module->methods->open() 调用module的open方法
                            |          |        |            +--> adev_open()
                            |          |        |                +--> 一大堆的函数和变量的初始化
                            |          |        |                |    voice_init()
                            |          |        |                |    platform_init() --> 与平台相关的初始化,主要就是xml acdb的初始化,会与驱动打交道,具体不列了。
                            |          |        |                |    audio_extn_listen_init()
                            |          |        |                |    audio_extn_sound_trigger_init()
                            |          |        |                |    可视化和offload音效加载
                            |          |        +-->             +--> audio_extn_utils_update_streams_output_cfg_list() Android 5.0增加了个这么个东西,与output config有关,不知拿来干嘛的。
                            |          +    如果是第一次加载并且HAL支持master volume/mute, 则使用主HAL提供的做为当前的master volue/mute设置
                            |          +    audio_module_handle_t handle = nextUniqueId();
                            |          +    mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
                            |          +    上面两句就是生成唯一的标识,然后new了个AudioHwDevice(),传进了HAL所获得的dev,相当于进行了C++类和C调用的转换
                            |          +    然后把handle和设备加到mAudioHwDevs向量里,这样就有了handle和AudioHwDevice()或者说HAL模块的一一对应关系
                            ^          +    以后通过查找handl就可以找到对应的HAL操作
                            +----------+--> return handle;注意这是module的handle

module处理完了,又通过两个子的for循环,分别处理OutputProfiles和InputProfiles

对outputprofile的处理,注意下面这句

if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
    continue;
}

也就是说有direct flag的都略过了, 后面的openoutput打开的其实只有primary和low_latency以及voice_tx的设备,
voice_tx这个名字很奇怪,我觉得应该是input设备,为什么要放在output里呢?不明白。
然后根据outProfile生成了个类 new AudioOutputDescriptor();

AudioPolicyManager.cpp
  for mHwModules
    for mHwModules[i]->mOutputProfiles
      sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile);
      然后重点是 openOutput()打开输入流
      audio_config_t config = AUDIO_CONFIG_INITIALIZER;
      config.sample_rate = outputDesc->mSamplingRate;
      config.channel_mask = outputDesc->mChannelMask;
      config.format = outputDesc->mFormat;
      audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
      status_t status = mpClientInterface->openOutput(outProfile->mModule->mHandle,
                            +--> 也是通过AudioPolicyClientImpl.cpp中转
                                +--> 最终调用 af->openOutput()
                                    +--> sp<PlaybackThread> thread = openOutput_l(module, output, config, *devices, address, flags); //注意返回的是个线程
                                    |    ^   +--> findSuitableHwDev_l() 从上面AF加载module的向量mAudioHwDevs里查找
                                    |    |   +    audio_hw_device_t *hwDevHal = outHwDev->hwDevice();也就是指向HAL的那一大堆函数
                                    |    |   +   *output = nextUniqueId(); 如果handler为空,则生成个(初始化传下来的为空)。
                                    |    |   +    hwDevHal->open_output_stream() AHAL中那一大堆函数中的open_output_stream()
                                    |    |   +        +--> adev_open_output_stream()
                                    |    |   |            +--> 根据传进去的out, config和别的进行一大堆的初始化
                                    |    |   |            | 与流相关的一大堆函数初始化,这些函数以out_开头,
                                    |    |   |            | (而不是加载module的与adev_开头), 也就是说与module/设备相关的以
                                    |    |   |            | adev_开关,与流相关的以out_/in_开头。
                                    |    |   |            +--> 从代码上看,没打开kernel的流,即这个open_output_stream并不是要打开硬件流。
                                    |    |   +    AudioStreamOut *outputStream = new AudioStreamOut(outHwDev, outStream, flags); 根据打开的strem和hwdev,又new了个新的东东,将他们关联起来。
                                    |    |   +    根据flag生成相应的线程
                                    |    |   +    如果有AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD => new OffloadThread()
                                    |    |   +    AUDIO_OUTPUT_FLAG_DIRECT => new DirectOutputThread()
                                    |    |   +    否则生成new MixerThread()
                                    |    |   +    ********还记得for循环里如果有direct flag则略过没? 所以应该初始化时只生成了MixerThread() *******
                                    |    |   +    这几个thread以后有需要再看构造了什么。
                                    |    ^   +    mPlaybackThreads.add(*output, thread); 将handler与thead对应,加到播放线程向量里
                                    |    +---+--> return thread;
                                    +    // notify client processes of the new output creation
                                    +    thread->audioConfigChanged(AudioSystem::OUTPUT_OPENED);通知IO改变了,这个代码看得有点晕,以后再看。
                                    +--> mPrimaryHardwareDev->hwDevice()->set_mode(mPrimaryHardwareDev->hwDevice(), mMode);如果flags有primary,再设置下模式。
  
      然后如果有  AUDIO_OUTPUT_FLAG_PRIMARY mPrimaryOutput = output;
      addOutput(output, outputDesc); //将output流的handler (AF::openOutput_l()生成)与描述关联
      setOutputDevice(); //设置输出,具体的不看了。

outputprofile 处理完后又是InputProfile
过程大致也差不多,具体不看了。
然后对错误的处理,
再调用updateDevicesAndOutputs();更新下也就构造完了

4. 总结

总结APM构造干的事情:
解析audio_policy.conf
根据解析出来的module,加载对应的lib
继续处理解析结果中的outputprofile, inputprofile,打开流,创建相应的线程


Atom
26 声望30 粉丝

带着问题看code