• 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的关键。



     
  • 相关阅读:
    eslint 的 env 配置是干嘛使的?
    cookie httpOnly 打勾
    如何定制 antd 的样式(theme)
    剑指 Offer 66. 构建乘积数组
    剑指 Offer 65. 不用加减乘除做加法
    剑指 Offer 62. 圆圈中最后剩下的数字
    剑指 Offer 61. 扑克牌中的顺子
    剑指 Offer 59
    剑指 Offer 58
    剑指 Offer 58
  • 原文地址:https://www.cnblogs.com/-glb/p/14255710.html
Copyright © 2020-2023  润新知