• AudioPolicyService启动过程分析(一)


    概述:

    AudioPolicyService做什么事情呢?简单来说,比如应用程序要播放一段声音,声音从哪个设备上播放出来。这些都是通过AudioPolicyService来决定的。

    假设android系统中有两个声卡设备:

    1)问默认声卡是哪个?

    由厂家决定

    2)从哪个设备上播放声音呢?耳机还是喇叭

    耳机、喇叭这些硬件配置从驱动中是看不出来的,那么声卡1中的耳机和喇叭如何告知Android系统呢?

    由厂家决定

    那厂家是如何决定的呢?

    此时AudioPolicyService服务就该出场了,该服务主要做如下几项工作:
    1)读取解析配置文件,声卡设备会根据配置文件进行选择。
    对于配置文件有两个:
    对于Android7.0之前,使用audio_policy.conf文件
    从Android7.0之后,又出现了一个audio_policy_configuration.xml文件。具体使用哪一个,由一个宏来控制。
    2)对于每个声卡,在Android音频系统中都会存在一个线程与之对应。从逻辑意义上说,有一个output,一个output对应一个或多个设备,同时一个output还对应一个线程。
    3)对于硬件的操作是由AudioFlinger完成的,但是AudioFlinger不能主动做任何事情。
    4)AudioPolicyService根据配置文件,调用AudioFlinger的服务,来打开output,创建线程。有了这些线程后,应用程序就可以把声音数据发给这些线程了。

    1. mediaserver加载

    AudioPolicyService是android音频系统的两大服务之一,另一个服务是AudioFliger。这两个服务都是在系统启动时由MediaServer加载。加载的代码位于:

    /frameworks/av/media/audioserver/main_audioserver.cpp

    int main(int argc __unused, char** argv)
    {
      .......
    AudioFlinger::instantiate();//创建AudioFlinger对象,服务名为"media.audio_flinger"
    ....... AudioPolicyService::instantiate();//创建AudioPolicyService对象,服务名为"media.audio_policy" ....... }

    2.可执行文件mediaserver

    看一个可执行文件,通常会首先查看其Android.mk文件,位于:

    /frameworks/av/media/mediaserver/Android.mk

    LOCAL_PATH:= $(call my-dir)
    .......
    include $(CLEAR_VARS) LOCAL_SRC_FILES:= main_mediaserver.cpp ........ LOCAL_MODULE:= mediaserver LOCAL_32_BIT_ONLY := true LOCAL_INIT_RC := mediaserver.rc LOCAL_CFLAGS := -Werror -Wall include $(BUILD_EXECUTABLE)

    对于该mk文件,我们重点关注3个地方:

    LOCAL_SRC_FILES:= main_mediaserver.cpp   //存放源程序的地方

    LOCAL_MODULE:= mediaserver //源文件最终被编译成的可执行文件mediaserver
    LOCAL_INIT_RC := mediaserver.rc

    2.1 mediaserver.rc

    /frameworks/av/media/mediaserver/mediaserver.rc

    service media /system/bin/mediaserver
        class main
        user media
        group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
        ioprio rt 4
        writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks

    3. AudioPolicyService::instantiate

    AudioPlicyService类中并没有instantiate函数,那么肯定是从父类中继承得到的。

    /frameworks/av/services/audiopolicy/service/AudioPolicyService.h

    class AudioPolicyService :
        public BinderService<AudioPolicyService>,
        public BnAudioPolicyService,
        public IBinder::DeathRecipient
    {
        friend class BinderService<AudioPolicyService>;
    
    public:
        // for BinderService
        static const char *getServiceName() ANDROID_API { return "media.audio_policy"; }

    在代码中搜索,可以发现instantiate函数是在BinderService类中定义的。

    /frameworks/native/libs/binder/include/binder/BinderService.h

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

    从上面的代码可以看出,AudioPolicyService::instantiate()实际上调用了publish函数,publish函数实际上调用了addService函数。在addService函数中,实现了3个作用:

    3.1 SERVICE::getServiceName()

    因为BinderService是类模板,又因为AudioPolicyService::instantiate(),所以此处的SERVICE就是类AudioPolicyService类。

    因此SERVICE::getServiceName()实际上调用了AudioPolicyService类中的成员函数getServiceName.

    static const char *getServiceName() ANDROID_API { return "media.audio_policy"; }

    将返回一个media.audio_policy的服务

    3.2 new SERVICE

    调用AudioPolicyService的构造函数,创建了一个AudioPolicyService的对象,做一些初始化的工作。

    /frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp

    AudioPolicyService::AudioPolicyService()
        : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
          mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
    {
    }

    3.3 调用AudioPolicyService::onFirstRef()

    由于sm是sp<IServiceManager>强引用类型的指针,所以在第一次调用AudioPolicyService模块时,会调用AudioPolicyService::onFirstRef()

    /frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp

    void AudioPolicyService::onFirstRef()
    {
        {
            Mutex::Autolock _l(mLock);
    
            // start tone playback thread,用于播放tone音,tone是音调的意思
            mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
            // start audio commands thread,用于执行audio命令
            mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
            // start output activity command thread,用于执行audio输出命令
            mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
            //实例化AudioPolicyClient对象
            mAudioPolicyClient = new AudioPolicyClient(this);
            //实例化AudioPolicyManager对象
            mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
        }
        // load audio processing modules
        //初始化音效相关
        sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
        {
                   mAudioPolicyEffects = audioPolicyEffects;
        }
    
    }

     3.3.1 new AudioPolicyClient

    创建了一个AudioPolicyClient的对象,AudioPolicyClient的构造函数在

     /frameworks/av/services/audiopolicy/service/AudioPolicyService.h中。

     class AudioPolicyClient : public AudioPolicyClientInterface
        {
         public:
            explicit AudioPolicyClient(AudioPolicyService *service) : mAudioPolicyService(service) {}
         .....
        }
     AudioPolicyService *mAudioPolicyService,mAudioPolicyService是类AudioPolicyService的一个指针。在AudioPolicyClient构造函数中,实际上只是将传进来的service指针
    赋值给了mAudioPolicyService。service是什么,就是传进来的this指针,this指针指代当前的AudioPolicyService类的一个指针。
    在这个地方设计到了C++的基本知识,首先会调用父类AudioPolicyClientInterface的构造函数,然后调用成员变量的构造函数,mAudioPolicyService是一个AudioPolicyService的对象,最后
    调用自己的构造函数。new AudioPolicyClient对象,会涉及到三个构造函数的调用哦。
    3.3.2 createAudioPolicyManager(mAudioPolicyClient)
    /frameworks/av/services/audiopolicy/manager/AudioPolicyFactory.cpp
    extern "C" AudioPolicyInterface* createAudioPolicyManager(
            AudioPolicyClientInterface *clientInterface)
    {
        return new AudioPolicyManager(clientInterface);
    }
    new AudioPolicyManager(clientInterface)将会调用类AudioPolicyManager的构造函数,接下来将重点分析该构造函数,这是我们分析AudioPolicyService的关键。



     
  • 相关阅读:
    Nebula3的Input系统
    Nebula3学习笔记(7): 脚本系统
    项目经理成长日记(4)——态度决定一切
    Nebula3学习笔记(2): 核心库
    Nebula3学习笔记(1): 序
    魔兽争霸的地图验证漏洞和作弊图原理,兼谈魔兽联机机制[转载]
    Nebula3的多线程架构
    项目经理成长日记(5)——五指有长短,能力各不同
    Nebula3资源子系统
    Nebula3的场景管理
  • 原文地址:https://www.cnblogs.com/-glb/p/14255710.html
Copyright © 2020-2023  润新知