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/audioserverclass coreuser 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/tasksonrestart 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=1stop audioserver
on property:vts.native_server.on=0start 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 hackstrcpy(argv[0], "media.log");sp<ProcessState> proc(ProcessState::self());MediaLogService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();//省略。。。。。。。。} else {// all other servicesif (doLog) {prctl(PR_SET_PDEATHSIG, SIGKILL);   // if parent media.log dies before me, kill me alsosetpgid(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 threadmTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);// start audio commands threadmAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);// start output activity command threadmOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);mAudioPolicyClient = new AudioPolicyClient(this);mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);}// load audio processing modulessp<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_CONFif (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {#elseif ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, getConfig()) != NO_ERROR)&& (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, getConfig()) != NO_ERROR)) {#endifALOGE("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启动相关推荐

  1. Android 音频源码分析——AndroidRecord录音(一)

    Android 音频源码分析--AndroidRecord录音(一) Android 音频源码分析--AndroidRecord录音(二) Android 音频源码分析--AndroidRecord音 ...

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

    Android 音频源码分析--AndroidRecord录音(一) Android 音频源码分析--AndroidRecord录音(二) Android 音频源码分析--AndroidRecord音 ...

  3. Android 音频源码分析——音频设备切换(插入耳机)

    源码分析基于android9.0 通常带线耳机分类 模拟耳机 平时常用的3.5mm或6.3mm接口耳机,接收模拟信号(音频数据需要先处理,转码成pcm格式) Android中模拟耳机由WiredAcc ...

  4. Android 音频源码分析——音量调节流程

    源码分析基于android9.0 一.声音类型 对于大多数手机用户来说,操作手机音量按键可以看到,声音类型分为四种:媒体.铃声.闹钟.通话,但是其系统内部则分为十几种类型. 声⾳类型用来区分不同播放用 ...

  5. Wifi模块—源码分析Wifi启动(Android P)

    一.前言 Android P在wifi这块改动挺大的,Wifi到AndoidO之后不再使用jni,所以AndroidP也一样不再使用jni来实现Java代码与本地的C/C++代码交互,而是使用HIDL ...

  6. Wifi模块—源码分析Wifi启动2(Android P)

    一 前言 在上一篇分析了wifi启动的流程,从Android应用层一直分析到了Java框架层,这次我们接着往下走流程.如果没有看上一篇的建议先回头看看   Wifi模块-源码分析Wifi启动1(And ...

  7. Android HandlerThread 源码分析

    HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我们又有一 个耗时任务需要执行,我们不得不重新创建 ...

  8. 【Android SDM660源码分析】- 02 - UEFI XBL QcomChargerApp充电流程代码分析

    [Android SDM660源码分析]- 02 - UEFI XBL QcomChargerApp充电流程代码分析 一.加载 UEFI 默认应用程序 1.1 LaunchDefaultBDSApps ...

  9. 【Android SDM660源码分析】- 01 - 如何创建 UEFI XBL Protocol DXE_DRIVER 驱动及UEFI_APPLICATION 应用程序

    [Android SDM660源码分析]- 01 - 如何创建 UEFI XBL Protocol DXE_DRIVER 驱动及UEFI_APPLICATION 应用程序 一.创建DXE_DRIVER ...

  10. Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7)【转】...

    原文地址:Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.c ...

最新文章

  1. backup(full,diff,log)备份并清理过时备份
  2. Kotlin特色之object、let、with、run、apply、also函数的使用
  3. MyEclipse 中文乱码
  4. 矩阵分析与多元统计1 线性空间与线性变换1
  5. 总结:ps aux指令
  6. Exception in thread main expected 'document start', but found BlockMappingStart in 'reader'(测试了)
  7. jboss eap 7.0_创建委托登录模块(用于JBoss EAP 6.1)
  8. H264 CAVLC 研究
  9. 如何开发一个扫雷小游戏?
  10. php对象数字属性,PHP获取对象的纯数字属性
  11. Swift基础--通知,代理和block的使用抉择以及Swift中的代理
  12. python实现给定一个列表判断里面是否有重复元素
  13. 泛微 E9开发视频教程
  14. python正则表达式match方法_Python match()函数:匹配正则表达式
  15. Win10__查看设备管理器中的端口
  16. jQuery淡入浅出
  17. RCP Editor 常见错误处理方法
  18. matlab 隐写分析,RS隐写分析.ppt
  19. 来了,Chrome Canary 版新增网页广告屏蔽功能
  20. 触摸屏与单片机通讯c语言程序设计,触摸屏与单片机的通信实现

热门文章

  1. 按键精灵大漠找字FindStrFast 函数封装
  2. 禁用win10触摸屏手势_怎样禁用、启用Win10平板边缘滑动手势
  3. python中day_python day02
  4. java生成xlsx文件
  5. 怎么把图片转换成表格?这三种办法值得收藏
  6. 2021-03-12
  7. 如果时间不够 ,无法进行充分的测试怎么办?
  8. 从表象到本质,包你一文看懂NFT
  9. 2019年2月已到,Java 8要收费了吗?
  10. matlab求3db函数,数字信号处理第二章习题26、30、32解答(包括matlab运行程序)