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();
主要工作:
- 启动AudioFlinger;
- 启动AudioPolicyService;
- 如果支持AAudioService,启动它;
- 启动语音识别模块SoundTriggerHwService;
- 创建线程池,并将当前线程加入线程池。
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();
;
- 获取IServiceManager;
- new SERVICE(),对应new AudioFlinger();
- 将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();
- 创建tone 播放线程并启动;
- 创建audio command线程并启动;
- 创建audio 输出命令线程并启动;
- 创建AudioPolicyClient对象,AudioFlinger和AudioPolicyService通信的中间;
- 创建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 音频源码分析——AudioTrack设备选择
Android 音频源码分析——AudioTrack设备选择
Android 音频源码分析——Thread Track分析