Android 音频源码分析——audioserver启动

Posted VNanyesheshou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 音频源码分析——audioserver启动相关的知识,希望对你有一定的参考价值。

Android 音频源码分析——AndroidRecord录音(一)
Android 音频源码分析——AndroidRecord录音(二)
Android 音频源码分析——AndroidRecord音频数据传输流程
Android 音频源码分析——audioserver启动

该源码分析基于android9.0

 Android音频系统中,有两大service:AudioFlinger和AudioPolicy,这两个服务都运行在audioservr进程中。这里来整理以下audioserver启动流程。

一、 加载audioserver.rc

Android系统启动:加载引导程序-》引导程序-》Linux内核启动-》启动init进程-》zygote进程-》SystemServer-》Launcher。

init进程对应main函数

system/core/init/init.cpp

int main(int argc, char** argv) 
	//......
    LoadBootScripts(am, sm);
    //......

接着看LoadBootScripts

static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) 
    Parser parser = CreateParser(action_manager, service_list);

    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) 
        parser.ParseConfig("/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) 
            late_import_paths.emplace_back("/system/etc/init");
        
        if (!parser.ParseConfig("/product/etc/init")) 
            late_import_paths.emplace_back("/product/etc/init");
        

        if (!parser.ParseConfig("/odm/etc/init")) 
            late_import_paths.emplace_back("/odm/etc/init");
        
        if (!parser.ParseConfig("/vendor/etc/init")) 
            late_import_paths.emplace_back("/vendor/etc/init");
        
     else 
        parser.ParseConfig(bootscript);
    

LoadBootScrips,会首先加载init.rc文件,然后会加载/system/etc/init/、/product/etc/init/、/odm/etc/init/、/vendor/etc/init目录下的rc文件。而audioserver.rc位于/system/etc/init 目录下。

二、 启动audioserver进程

看一下audioserver.rc文件,init进程中加载audioserver.rc文件,并启动audioserver进程。

frameworks/av/media/audioserver/audioserver.rc

service audioserver /system/bin/audioserver
    class core
    user audioserver  #设置所有者
    # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct  #设置所属组
    ioprio rt 4  #io优先级
    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
    onrestart restart vendor.audio-hal-2-0
    # Keep the original service name for backward compatibility when upgrading
    # O-MR1 devices with framework-only.
    onrestart restart audio-hal-2-0   #重启该进程时,执行restart audio-hal-2-0命令

on property:vts.native_server.on=1
    stop audioserver
on property:vts.native_server.on=0
    start audioserver
   

三、 audioserver main

frameworks/av/media/audioserver/main_audioserver.cpp

int main(int argc __unused, char **argv)


    bool doLog = (bool) property_get_bool("ro.test_harness", 0);

    pid_t childPid;
    if (doLog && (childPid = fork()) != 0) 
      	//如果doLog为true,fork子进程。
        // media.log service
        //prctl(PR_SET_NAME, (unsigned long) "media.log", 0, 0, 0);
        // unfortunately ps ignores PR_SET_NAME for the main thread, so use this ugly hack
        strcpy(argv[0], "media.log");
        sp<ProcessState> proc(ProcessState::self());
        MediaLogService::instantiate();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
        //省略。。。。。。。。
     else 
        // all other services
        if (doLog) 
            prctl(PR_SET_PDEATHSIG, SIGKILL);   // if parent media.log dies before me, kill me also
            setpgid(0, 0);                      // but if I die first, don't kill my parent
        
        android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm = defaultServiceManager();
        ALOGI("ServiceManager: %p", sm.get());
        AudioFlinger::instantiate();
        AudioPolicyService::instantiate();

        // AAudioService should only be used in OC-MR1 and later.
        // And only enable the AAudioService if the system MMAP policy explicitly allows it.
        // This prevents a client from misusing AAudioService when it is not supported.
        aaudio_policy_t mmapPolicy = property_get_int32(AAUDIO_PROP_MMAP_POLICY,
                                                        AAUDIO_POLICY_NEVER);
        if (mmapPolicy == AAUDIO_POLICY_AUTO || mmapPolicy == AAUDIO_POLICY_ALWAYS) 
            AAudioService::instantiate();
        

        SoundTriggerHwService::instantiate();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    


主要工作:

  1. 启动AudioFlinger;
  2. 启动AudioPolicyService;
  3. 如果支持AAudioService,启动它;
  4. 启动语音识别模块SoundTriggerHwService;
  5. 创建线程池,并将当前线程加入线程池。

1. AudioFlinger初始化

接着看AudioFlinger::instantiate()。AudioFlinger并没有实现instantiate函数,直接在其父类找到对应函数。

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

template<typename SERVICE>
class BinderService

public:
    static status_t publish(bool allowIsolated = false,
                            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) 
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
                              dumpFlags);
    

    static void instantiate()  publish(); 
;
  1. 获取IServiceManager;
  2. new SERVICE(),对应new AudioFlinger();
  3. 将AudioFlinger注册到ServiceManager,方便后续别的进程使用该服务。

接着看AudioFlinger初始化方法,主要默认参数赋值。智能指针首次初始化会调用onFirstRef函数。

创建PatchPanel,mMode设为AUDIO_MODE_NORMAL。

AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
      mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
      mPrimaryHardwareDev(NULL),
      mAudioHwDevs(NULL),
      mHardwareStatus(AUDIO_HW_IDLE),
      mMasterVolume(1.0f),
      mMasterMute(false),
      mMode(AUDIO_MODE_INVALID),
      mBtNrecIsOff(false),
      mIsLowRamDevice(true),
      mIsDeviceTypeKnown(false),
      mTotalMemory(0),
      mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
      mGlobalEffectEnableTime(0),
      mSystemReady(false)

    // reset battery stats.
    // if the audio service has crashed, battery stats could be left
    // in bad state, reset the state upon service start.
    BatteryNotifier::getInstance().noteResetAudio();

    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();


void AudioFlinger::onFirstRef()

    Mutex::Autolock _l(mLock);
    /* TODO: move all this work into an Init() function */
    char val_str[PROPERTY_VALUE_MAX] =  0 ;
    if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) 
        uint32_t int_val;
        if (1 == sscanf(val_str, "%u", &int_val)) 
            mStandbyTimeInNsecs = milliseconds(int_val);
         else 
            mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
        
    
    mPatchPanel = new PatchPanel(this);
    mMode = AUDIO_MODE_NORMAL;
    gAudioFlinger = this;

2. AudioPolicyService初始化

AudioPolicyService和AudioFlinger都是BinderService子类,其instantiate是类似的,创建AudioPolicyService,注册到ServiceManager中。

接着看AudioPolicyService初始化。

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



void AudioPolicyService::onFirstRef()

    
        Mutex::Autolock _l(mLock);
        // start tone playback thread
        mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
        // start audio commands thread
        mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
        // start output activity command thread
        mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);

        mAudioPolicyClient = new AudioPolicyClient(this);
        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
    
    // load audio processing modules
    sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
    
        Mutex::Autolock _l(mLock);
        mAudioPolicyEffects = audioPolicyEffects;
    

    mUidPolicy = new UidPolicy(this);
    mUidPolicy->registerSelf();

  1. 创建tone 播放线程并启动;
  2. 创建audio command线程并启动;
  3. 创建audio 输出命令线程并启动;
  4. 创建AudioPolicyClient对象,AudioFlinger和AudioPolicyService通信的中间;
  5. 创建AudioPolicyManage对象;

接着看一下AudioPolicyManager初始化

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
        : AudioPolicyManager(clientInterface, false /*forTesting*/)

    loadConfig();
    initialize();


void AudioPolicyManager::loadConfig() 
#ifdef USE_XML_AUDIO_POLICY_CONF
    if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) 
#else
    if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, getConfig()) != NO_ERROR)
           && (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, getConfig()) != NO_ERROR)) 
#endif
        ALOGE("could not load audio policy configuration file, setting defaults");
        getConfig().setDefault();
    

loadConfig加载音频配置文件,通过USE_XML_AUDIO_POLICY_CONF 区分加载 audio_policy_configuration.xml 还是audio_policy.conf配置文件,Andorid 7.0之后通常使用audio_policy_configuration.xml 了。

接着看initialize

status_t AudioPolicyManager::initialize() 
    for (const auto& hwModule : mHwModulesAll) 
        hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
        if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) 
            ALOGW("could not open HW module %s", hwModule->getName());
            continue;
        
        mHwModules.push_back(hwModule);
        // open all output streams needed to access attached devices
        // except for direct output streams that are only opened when they are actually
        // required by an app.
        // This also validates mAvailableOutputDevices list
        
        //.....省略
    updateDevicesAndOutputs();
    return status;

依次加载 HwModule 并打开其所含 profile 的 outputStream 及 inputStream。audio module模块包括:primary、A2DP、USB、remote_submix、hearing_aid。

四、总结

audioserver启动会开启AudioFlinger和AudioPolicyService两个服务,这两个服务会加载配置文件,解析音频输入输出硬件信息,并且加载HIDL,建立与hadware通信的连接。至此音频模块就加载完成了。

以上是关于Android 音频源码分析——audioserver启动的主要内容,如果未能解决你的问题,请参考以下文章

Android 音频源码分析——AudioFlinger

Android 音频源码分析——AudioTrack设备选择

Android 音频源码分析——AudioTrack设备选择

Android 音频源码分析——Thread Track分析

Android 音频源码分析——Thread Track分析

android 音频子系统-Surfaceflinger