赞
踩
本文基于 Android 9.0 进行分析
自Android6.0后,Audio模块便和Media模块分离开,成为独立模块。
它的启动入口位于:
frameworks/av/media/audioserver/main_audioserver.cpp
由frameworks/av/media/audioserver/audioserver.rc文件引导.主要作用是调用了AudioFlinger和AudioPolicyService这两大模块的初始化接口。
1.设备开机,系统启动时将执行 /system/etc/init/audioserver.rc ,运行 /system/bin/ 目录下的 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 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 disabled on property:vts.native_server.on=1 stop audioserver on property:vts.native_server.on=0 start audioserver
2.进程入口:
int main(int argc __unused, char **argv) { ...... if (doLog && (childPid = fork()) != 0){ ... }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(); } }
audioserver 进程会依次对 AudioFlinger、AudioPolicyService进行实例化
其调用了AudioFlinger和AudioPolicyServer的instantiate()接口,是个单例模式。然后就是启动并加入线程池
3.audiofinger的启动调用流程:
在AudioFlinger类里找不到这个instantiate()接口,按照谷歌的惯性自然要去它的父类寻找,如下:
class AudioFlinger :
public BinderService<AudioFlinger>,
public BnAudioFlinger
{
friend class BinderService<AudioFlinger>; // for AudioFlinger()
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 publishAndJoinThreadPool( bool allowIsolated = false, int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) { publish(allowIsolated, dumpFlags); joinThreadPool(); } static void instantiate() { publish(); }
new了一个SERVICE(即AudioFlinger),并注册到Manager服务里,方便其他模块申请服务
AudioFlinger的构造函数:
AudioFlinger::AudioFlinger() : BnAudioFlinger(), mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()), mPrimaryHardwareDev(NULL), mAudioHwDevs(NULL), mHardwareStatus(AUDIO_HW_IDLE), mMasterVolume(1.0f), mMasterMute(false), // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX), mMode(AUDIO_MODE_INVALID), mBtNrecIsOff(false), mIsLowRamDevice(true), mIsDeviceTypeKnown(false), mTotalMemory(0), mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes), mGlobalEffectEnableTime(0), mSystemReady(false)
所有使用智能指针(继承RefBase)的类在第一次创建时都会调用refBase()函数
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); ALOGI("Using %u mSec as standby time.", int_val); } else { mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs; ALOGI("Using default %u mSec as standby time.", (uint32_t)(mStandbyTimeInNsecs / 1000000)); } } mPatchPanel = new PatchPanel(this); mMode = AUDIO_MODE_NORMAL; gAudioFlinger = this; }
4.AudioPolicyService的启动调用流程:
同AudioFlinger:
构造函数:
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
{
}
onFirstRef:
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(); }
extern "C" AudioPolicyInterface* createAudioPolicyManager(
AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManager(clientInterface);
}
AudioPolicyManager 的构造函数将解析音频策略配置文件,从而获取到设备所支持的音频设备信息(包括设备是否支持 Offload、Direct 模式输出,各输入输出 profile 所支持的采样率、通道数、数据格式等),加载全部 HwModule,为之创建所有非 direct 输出类型的 outputStream 和所有 inputStream,并创建相应的 playbackThread 或 recordThread 线程。需要注意的是,Android 7.0上的音频策略配置文件开始使用 XML 格式,其文件名为 audio_policy_configuration.xml,而在之前的版本上音频策略配置文件为 audio_policy.conf。frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp 中
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();
}
}
status_t AudioPolicyManager::initialize(){ mVolumeCurves->initializeVolumeCurves(getConfig().isSpeakerDrcEnabled()); // Once policy config has been parsed, retrieve an instance of the engine and initialize it. audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance(); if (!engineInstance) { ALOGE("%s: Could not get an instance of policy engine", __FUNCTION__); return NO_INIT; } // Retrieve the Policy Manager Interface mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>(); if (mEngine == NULL) { ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__); return NO_INIT; } mEngine->setObserver(this); status_t status = mEngine->initCheck(); if (status != NO_ERROR) { LOG_FATAL("Policy engine not initialized(err=%d)", status); return status; } // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices // open all output streams needed to access attached devices audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types(); audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; 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 for (const auto& outProfile : hwModule->getOutputProfiles()) { if (!outProfile->canOpenNewIo()) { ALOGE("Invalid Output profile max open count %u for profile %s", outProfile->maxOpenCount, outProfile->getTagName().c_str()); continue; } if (!outProfile->hasSupportedDevices()) { ALOGW("Output profile contains no device on module %s", hwModule->getName()); continue; } if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) { mTtsOutputAvailable = true; } if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) { continue; } audio_devices_t profileType = outProfile->getSupportedDevicesType(); if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) { profileType = mDefaultOutputDevice->type(); } else { // chose first device present in profile's SupportedDevices also part of // outputDeviceTypes profileType = outProfile->getSupportedDeviceForType(outputDeviceTypes); } if ((profileType & outputDeviceTypes) == 0) { continue; } sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile, mpClientInterface); const DeviceVector &supportedDevices = outProfile->getSupportedDevices(); const DeviceVector &devicesForType = supportedDevices.getDevicesFromType(profileType); String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress : String8(""); audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; status_t status = outputDesc->open(nullptr, profileType, address, AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output); if (status != NO_ERROR) { ALOGW("Cannot open output stream for device %08x on hw module %s", outputDesc->mDevice, hwModule->getName()); } else { for (const auto& dev : supportedDevices) { ssize_t index = mAvailableOutputDevices.indexOf(dev); // give a valid ID to an attached device once confirmed it is reachable if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) { mAvailableOutputDevices[index]->attach(hwModule); } } if (mPrimaryOutput == 0 && outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) { mPrimaryOutput = outputDesc; } addOutput(output, outputDesc); setOutputDevice(outputDesc, profileType, true, 0, NULL, address); } } // open input streams needed to access attached devices to validate // mAvailableInputDevices list for (const auto& inProfile : hwModule->getInputProfiles()) { if (!inProfile->canOpenNewIo()) { ALOGE("Invalid Input profile max open count %u for profile %s", inProfile->maxOpenCount, inProfile->getTagName().c_str()); continue; } if (!inProfile->hasSupportedDevices()) { ALOGW("Input profile contains no device on module %s", hwModule->getName()); continue; } // chose first device present in profile's SupportedDevices also part of // inputDeviceTypes audio_devices_t profileType = inProfile->getSupportedDeviceForType(inputDeviceTypes); if ((profileType & inputDeviceTypes) == 0) { continue; } sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile, mpClientInterface); DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(profileType); // the inputs vector must be of size >= 1, but we don't want to crash here String8 address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress : String8(""); ALOGV(" for input device 0x%x using address %s", profileType, address.string()); ALOGE_IF(inputDevices.size() == 0, "Input device list is empty!"); audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; status_t status = inputDesc->open(nullptr, profileType, address, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE, &input); if (status == NO_ERROR) { for (const auto& dev : inProfile->getSupportedDevices()) { ssize_t index = mAvailableInputDevices.indexOf(dev); // give a valid ID to an attached device once confirmed it is reachable if (index >= 0) { sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index]; if (!devDesc->isAttached()) { devDesc->attach(hwModule); devDesc->importAudioPort(inProfile, true); } } } inputDesc->close(); } else { ALOGW("Cannot open input stream for device %08x on hw module %s", profileType, hwModule->getName()); } } } // make sure all attached devices have been allocated a unique ID for (size_t i = 0; i < mAvailableOutputDevices.size();) { if (!mAvailableOutputDevices[i]->isAttached()) { ALOGW("Output device %08x unreachable", mAvailableOutputDevices[i]->type()); mAvailableOutputDevices.remove(mAvailableOutputDevices[i]); continue; } // The device is now validated and can be appended to the available devices of the engine mEngine->setDeviceConnectionState(mAvailableOutputDevices[i], AUDIO_POLICY_DEVICE_STATE_AVAILABLE); i++; } for (size_t i = 0; i < mAvailableInputDevices.size();) { if (!mAvailableInputDevices[i]->isAttached()) { ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->type()); mAvailableInputDevices.remove(mAvailableInputDevices[i]); continue; } // The device is now validated and can be appended to the available devices of the engine mEngine->setDeviceConnectionState(mAvailableInputDevices[i], AUDIO_POLICY_DEVICE_STATE_AVAILABLE); i++; } // make sure default device is reachable if (mDefaultOutputDevice == 0 || mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) { ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type()); status = NO_INIT; } // If microphones address is empty, set it according to device type for (size_t i = 0; i < mAvailableInputDevices.size(); i++) { if (mAvailableInputDevices[i]->mAddress.isEmpty()) { if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) { mAvailableInputDevices[i]->mAddress = String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS); } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) { mAvailableInputDevices[i]->mAddress = String8(AUDIO_BACK_MICROPHONE_ADDRESS); } } } if (mPrimaryOutput == 0) { ALOGE("Failed to open primary output"); status = NO_INIT; } updateDevicesAndOutputs(); return status; }
5.至此,Android 系统中音频模块的启动就完成了,两大关键音频组件 AudioFlinger 和 AudioPolicyService 均已创建并运行,设备所支持的音频输入输出硬件信息也已经被 AudioPolicyManager 所解析。如果此时发生了插入耳机等操作,则 AudioPolicyService 将会接收到底层通知并把 Audio Route 切换到 WiredHeadset 等响应配置;如果此时在 APP 发生了播放音乐的操作,则 AudioFlinger 会接收到上层通知并创建相应 Track。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。