1、音频服务初始化流程
当前版本:Android 12
大致的创建流程如下:
1.1 开机启动音频服务
音频服务在frameworks/av/media/audioserver/main_audioserver.cpp
中,这里会启动音频的AudioFlinger
和AudioPolicyService
两大组件,简单的流程如下:
经过上面流程之后,音频系统中会启动AudioFlinger
用于处理后面所有的音频播放,AudioFlinger
具体的功能后面再详细分析,AudioPolicyService
负责后面的音频策略的处理等流程,AudioFlinger
和AudioPolicyService
之间进行交互
frameworks\av\media\audioserver\main_audioserver.cpp
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
1.2 AudioFlinger
模块加载
通过上面流程会调用到AudioFlinger
的构造函数,进行AudioFlinger
模块的处理,流程如下:
AudioFlinger::AudioFlinger()
: 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),
mPatchPanel(this),
mDeviceEffectManager(this),
mSystemReady(false)
{
// Move the audio session unique ID generator start base as time passes to limit risk of
// generating the same ID again after an audioserver restart.
// This is important because clients will reuse previously allocated audio session IDs
// when reconnecting after an audioserver restart and newly allocated IDs may conflict with
// active clients.
// Moving the base by 1 for each elapsed second is a good compromise between avoiding overlap
// between allocation ranges and not reaching wrap around too soon.
timespec ts{};
clock_gettime(CLOCK_MONOTONIC, &ts);
// zero ID has a special meaning, so start allocation at least at AUDIO_UNIQUE_ID_USE_MAX
uint32_t movingBase = (uint32_t)std::max((long)1, ts.tv_sec);
// unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
mNextUniqueIds[use] =
((use == AUDIO_UNIQUE_ID_USE_SESSION || use == AUDIO_UNIQUE_ID_USE_CLIENT) ?
movingBase : 1) * AUDIO_UNIQUE_ID_USE_MAX;
}
#if 1
// FIXME See bug 165702394 and bug 168511485
const bool doLog = false;
#else
const bool doLog = property_get_bool("ro.test_harness", false);
#endif
if (doLog) {
mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
MemoryHeapBase::READ_ONLY);
(void) pthread_once(&sMediaLogOnce, sMediaLogInit);
}
// 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();
mMediaLogNotifier->run("MediaLogNotifier");
std::vector<pid_t> halPids;
mDevicesFactoryHal->getHalPids(&halPids);
TimeCheck::setAudioHalPids(halPids);
// Notify that we have started (also called when audioserver service restarts)
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
.record();
}
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));
}
}
mMode = AUDIO_MODE_NORMAL;
gAudioFlinger = this; // we are already refcounted, store into atomic pointer.
mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
}
在上面的构造函数中实例化了设备接口以及音效接口,此时AudioFlinger
模块已经成功创建出来,后面AudioPolicyService
创建出来后就可以和AudioFlinger
之间进行交互了
1.3 AudioPolicyService
模块加载
AudioPolicyService
负责音频的一些策略管理以及命令处理,具体的启动流程如下:
frameworks\av\services\audiopolicy\service\AudioPolicyService.cpp
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService(),
mAudioPolicyManager(NULL),
mAudioPolicyClient(NULL),
mPhoneState(AUDIO_MODE_INVALID),
mCaptureStateNotifier(false),
mCreateAudioPolicyManager(createAudioPolicyManager),
mDestroyAudioPolicyManager(destroyAudioPolicyManager) {
}
mCreateAudioPolicyManager是CreateAudioPolicyManagerInstance类型的实例
using CreateAudioPolicyManagerInstance = AudioPolicyInterface* (*)(AudioPolicyClientInterface*);
using DestroyAudioPolicyManagerInstance = void (*)(AudioPolicyInterface*);
CreateAudioPolicyManagerInstance是一个函数指针指向 createAudioPolicyManager
mDestroyAudioPolicyManager同理
mAudioPolicyManager = mCreateAudioPolicyManager(mAudioPolicyClient);
就相当于
createAudioPolicyManager(mAudioPolicyClient)
void AudioPolicyService::onFirstRef()
{
{
Mutex::Autolock _l(mLock);
// 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);
loadAudioPolicyManager();
mAudioPolicyManager = mCreateAudioPolicyManager(mAudioPolicyClient);
}
// load audio processing modules
sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects();
sp<UidPolicy> uidPolicy = new UidPolicy(this);
sp<SensorPrivacyPolicy> sensorPrivacyPolicy = new SensorPrivacyPolicy(this);
{
Mutex::Autolock _l(mLock);
mAudioPolicyEffects = audioPolicyEffects;
mUidPolicy = uidPolicy;
mSensorPrivacyPolicy = sensorPrivacyPolicy;
}
// @Rockchip For bootvideo
char value[PROPERTY_VALUE_MAX];
property_get("persist.sys.bootvideo.enable", value, "false");
if (!strcmp(value, "true")) {
mOutputCommandThread->registerUidCommand(uidPolicy);
ALOGD("bootvideo enable,delay run Policy registerSelf");
} else {
uidPolicy->registerSelf();
sensorPrivacyPolicy->registerSelf();
}
// @end
// Create spatializer if supported
if (mAudioPolicyManager != nullptr) {
Mutex::Autolock _l(mLock);
const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
AudioDeviceTypeAddrVector devices;
bool hasSpatializer = mAudioPolicyManager->canBeSpatialized(&attr, nullptr, devices);
if (hasSpatializer) {
mSpatializer = Spatializer::create(this);
}
}
AudioSystem::audioPolicyReady();
}
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);
status_t status = apm->initialize();
if (status != NO_ERROR) {
delete apm;
apm = nullptr;
}
return apm;
}
frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp
创建AudioPolicyManager
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
bool /*forTesting*/)
:
mUidCached(AID_AUDIOSERVER), // no need to call getuid(), there's only one of us running.
mpClientInterface(clientInterface),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false),
mMusicEffectOutput(AUDIO_IO_HANDLE_NONE)
{
}
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
: AudioPolicyManager(clientInterface, false /*forTesting*/)
{
loadConfig();
}
void AudioPolicyManager::loadConfig() {
if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
ALOGE("could not load audio policy configuration file, setting defaults");
getConfig().setDefault();
}
//TODO: b/193496180 use spatializer flag at audio HAL when available
getConfig().convertSpatializerFlag();
}
status_t AudioPolicyManager::initialize() {
{
auto engLib = EngineLibrary::load(
"libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");
if (!engLib) {
ALOGE("%s: Failed to load the engine library", __FUNCTION__);
return NO_INIT;
}
mEngine = engLib->createEngine();
if (mEngine == nullptr) {
ALOGE("%s: Failed to instantiate the APM engine", __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;
}
mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
// after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
// open all output streams needed to access attached devices
onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
// make sure default device is reachable
if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable",
mDefaultOutputDevice->toString().c_str());
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]->address().empty()) {
if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
} else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
}
}
}
ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
// Silence ALOGV statements
property_set("log.tag." LOG_TAG, "D");
updateDevicesAndOutputs();
return status;
}
- 这里调用的
createAudioPolicyManager
- 解析的配置文件包含
audio_policy_configuration.xml
,用于解析包含音频策略在内的一些配置文件 deserializeAudioPolicyFile
方法定义在frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
文件中primary_audio_policy_configuration.xml
文件解析流程配置解析- Engine配置分析
总结:
- 首先分析了从
AudioPolicyService
创建AudioPolicyManager
的流程,这里涉及到第三方自己的AudioPolicyManager
,所以中间多了一个AudioPolicyManagerSPRD
的创建- 有了
AudioPolicyManager
对象之后需要加载音频的一些配置文件,包括描述所有外部设备以及设备之间路由情况的primary_audio_policy_configuration.xml
,这个xml
文件解析之后会将内容存放到AudioPolicyManager
持有的AudioPolicyConfig
对象中,具体的作用我们后面分析- 加载完
xml
之后就是进行Engine
对象的创建,这个Engine
对象负责管理音频策略相关的内容Engine
对象创建完毕之后需要对xml
解析出来的内容进行处理,这部分涉及和AudioFlinger
的交互,放在后面一节讲述