研究Android多媒体已经有一段时间,特撰写关于android多媒体系列的文章,为了加深理解和认识,也希望能为想了解多媒体的同学提供帮助。
AudioPolicyServer看名字也能猜到应该和策略相关的一些功能,不错AudioPolicyServer正是音频策略的制定者,管理和运营所有android手机上的音频硬件,我们可以通过adb shell进入手机终端,进入cd /dev/snd/ 目录查看当前手机都有那些音频设备,会发现手机上的音频设备会很多。播放音乐,来电,响铃究竟是开启的是那个音频设备呢,某种Stream类型的音频应对应什么设备,AudioPolicyServer是怎样维护现有系统中的音频设备,各个设备之间如何切换,调节音量时调节是哪个设备呢,带着这些疑问来看看AudioPolicyServer是如何实现的。
一 首先让我们来看看与AudioPolicyServer相关联类的组织关系
1.1 AudioPolicyServer类继承IAudioPolicyServer类,为其他应用程序提供audio策略相关的功能,对外的唯一接口。
1.2 AudioPolicyManagerCustom或者AudioPolicyManagerBase,有些厂商会定制这个类,继承AudioPolicyManager,AudioPolicyManager是一个非常重要的一个类,策略的具体制定是由此类实施的,AudioPolicyServer调用AudioPolicyManager的实例来实现各种策略的功能
1.3 AudioPolicyClient类继承AudioPolicyClientInterface,AudioPolicyClient类负责与AudioFlinger的交互,AudioPolicyServer是策略的制定者,但策略的具体实施是由AudioFlinger类完成,AudioPolicyServer确定具体策略时,交给AudioPolicyClient,AudioPolicyClient在传达给AudioFlinger,AudioPolicyClient类似一个信使或者中介者。
1.4 EngineInstance类,主要为获取Engine实例提供接口,Engine类规定了具体策略相关的规定,并通过ManagerInterfaceImpl向AudioPolicyManager提供信息。
二 AudioPolicyServer初始化过程
AudioPolicyServer是在开机的时候被初始化的,源码位于
frameworks/av/media/mediaserver/main_mediaserver.cpp 中
int main(int argc __unused, char** argv)
{
signal(SIGPIPE, SIG_IGN);
......................
InitializeIcuOrDie();
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
//首先初始化AudioFlinger
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
CameraService::instantiate();
//在初始化AudioPolicyService
AudioPolicyService::instantiate();
SoundTriggerHwService::instantiate();
RadioService::instantiate();
#ifdef AUDIO_LISTEN_ENABLED
ALOGI("ListenService instantiated");
ListenService::instantiate();
#endif
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
}
2.1 AudioPolicyService::AudioPolicyService()构造函数
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
{
}
AudioPolicyService构造函数初始化几个变量,其他的就没做啥,当AudioPolicyService第一次别引用时触发AudioPolicyService::onFirstRef()函数,且只有第一次被引用才会被调用,以后的调用中不会在触发此函数。
void AudioPolicyService::onFirstRef()
{
char value[PROPERTY_VALUE_MAX];
const struct hw_module_t *module;
int forced_val;
int rc;
{
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);
#ifdef USE_LEGACY_AUDIO_POLICY
ALOGI("AudioPolicyService CSTOR in legacy mode");
/* instantiate the audio policy manager */
rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
if (rc) {
return;
}
rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
if (rc) {
return;
}
rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
&mpAudioPolicy);
ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
if (rc) {
return;
}
rc = mpAudioPolicy->init_check(mpAudioPolicy);
ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
if (rc) {
return;
}
ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
#else
ALOGI("AudioPolicyService CSTOR in new mode");
//创建AudioPolicyClient和AudioPolicyManager实例
mAudioPolicyClient = new AudioPolicyClient(this);
mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
#endif
}
// load audio processing modules
spaudioPolicyEffects = new AudioPolicyEffects();
{
Mutex::Autolock _l(mLock);
mAudioPolicyEffects = audioPolicyEffects;
}
}
AudioPolicyService首先创建了三个线程, mTonePlaybackThread用于音调的播放,mAudioCommandThread音频参数的传达,比如上层经常会掉用一些setParamter的方法,最终都会通过mAudioCommandThread线程传达下去mOutputCommandThread与通路相关一些操作。比如新建一个通路,释放一个通路等。宏USE_LEGACY_AUDIO_POLICY是否开启老版本的策略,这是为了兼容老的策略版本,本文是基于android5.0以上版本分析的,所以不去在看,即此宏没有被开启。
2.2 mAudioPolicyClient = new AudioPolicyClient(this);此处新建 AudioPolicyClient实例并将AudioPolicyService实例传给AudioPolicyClient,保存在mAudioPolicyClient变量中。 AudioPolicyClient类定义在frameworks/av/services/audiopolicy/service/AudioPolicyService.h,AudioPolicyClient具体实现在frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp文件中。
2.3 mAudioPolicyManager =createAudioPolicyManager(mAudioPolicyClient);创建AudioPolicyManager实例对象,保存在变量中mAudioPolicyManager,参数mAudioPolicyClient将AudioPolicyClient的实例传送到AudioPolicyManager实例中,这样AudioPolicyManager就可以直接调用AudioPolicyClient的功能,createAudioPolicyManager是一个c函数,部分厂家可能会对此修改,但不论厂家如何修改都会继承AudioPolicyManager类来做一些微调。
2.4 创建AudioPolicyManager实例时,AudioPolicyManager构造函数做了重要的工作,也是AudioPolicyService初始化的核心。
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
:
#ifdef AUDIO_POLICY_TEST
Thread(false),
#endif //AUDIO_POLICY_TEST
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
mSpeakerDrcEnabled(false),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
mBeaconMuted(false),
mTtsOutputAvailable(false)
{
//获取EngineInstance实例
audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
if (!engineInstance) {
ALOGE("%s: Could not get an instance of policy engine", __FUNCTION__);
return;
}
// 通过EngineInstance实例查询到AudioPolicyManagerInterface的实例
// mEngine是ManagerInterfaceImpl类的实例
mEngine = engineInstance->queryInterface();
if (mEngine == NULL) {
ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
return;
}
mEngine->setObserver(this);
status_t status = mEngine->initCheck();
ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status);
mUidCached = getuid();
mpClientInterface = clientInterface;
//设置默认输出设备为speaker
mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
//加载解析audio_policy.conf文件
if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE,
mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE,
mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
ALOGE("could not load audio policy configuration file, setting defaults");
defaultAudioPolicyConfig();
}
}
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
// must be done after reading the policy (since conditionned by Speaker Drc Enabling)
mEngine->initializeVolumeCurves(mSpeakerDrcEnabled);
// 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 (size_t i = 0; i < mHwModules.size(); i++) {
//通过mpClientInterface加载相应HwModule相应的库文件,mpClientInterface最终会调用
//audioflinger加载库文件
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
if (mHwModules[i]->mHandle == 0) {
ALOGW("could not open HW module %s", mHwModules[i]->mName);
continue;
}
// 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 (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
//
const sp outProfile = mHwModules[i]->mOutputProfiles[j];
if (outProfile->mSupportedDevices.isEmpty()) {
ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName);
continue;
}
if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_TTS) != 0) {
mTtsOutputAvailable = true;
}
if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
continue;
}
audio_devices_t profileType = outProfile->mSupportedDevices.types();
if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
profileType = mDefaultOutputDevice->type();
} else {
// chose first device present in mSupportedDevices also part of
// outputDeviceTypes
for (size_t k = 0; k < outProfile->mSupportedDevices.size(); k++) {
profileType = outProfile->mSupportedDevices[k]->type();
if ((profileType & outputDeviceTypes) != 0) {
break;
}
}
}
if ((profileType & outputDeviceTypes) == 0) {
continue;
}
sp outputDesc = new SwAudioOutputDescriptor(outProfile,
mpClientInterface);
outputDesc->mDevice = profileType;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = outputDesc->mSamplingRate;
config.channel_mask = outputDesc->mChannelMask;
config.format = outputDesc->mFormat;
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
//audiopolicyserver在加载audio_policy.conf之后,为各个hw module建立了几个软件通路,
//各个通路需要和audioflinger建立联系,每一个通路都有audio_io_handle_t与audioflinger建立对应关系
//APS通过ModuleHandle和audio_io_handle_t可以再audioflinger中找到对应的实体,每个audio_io_handle_t
//都对应一个PlaybackThread
status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
&output,
&config,
&outputDesc->mDevice,
String8(""),
&outputDesc->mLatency,
outputDesc->mFlags);
if (status != NO_ERROR) {
ALOGW("Cannot open output stream for device %08x on hw module %s",
outputDesc->mDevice,
mHwModules[i]->mName);
} else {
outputDesc->mSamplingRate = config.sample_rate;
outputDesc->mChannelMask = config.channel_mask;
outputDesc->mFormat = config.format;
for (size_t k = 0; k < outProfile->mSupportedDevices.size(); k++) {
audio_devices_t type = outProfile->mSupportedDevices[k]->type();
ssize_t index =
mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
// give a valid ID to an attached device once confirmed it is reachable
if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
mAvailableOutputDevices[index]->attach(mHwModules[i]);
}
}
if (mPrimaryOutput == 0 &&
outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
addOutput(output, outputDesc);
setOutputDevice(outputDesc,
outputDesc->mDevice,
true);
}
}
// open input streams needed to access attached devices to validate
// mAvailableInputDevices list
for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)
{
const sp inProfile = mHwModules[i]->mInputProfiles[j];
if (inProfile->mSupportedDevices.isEmpty()) {
ALOGW("Input profile contains no device on module %s", mHwModules[i]->mName);
continue;
}
// chose first device present in mSupportedDevices also part of
// inputDeviceTypes
audio_devices_t profileType = AUDIO_DEVICE_NONE;
for (size_t k = 0; k < inProfile->mSupportedDevices.size(); k++) {
profileType = inProfile->mSupportedDevices[k]->type();
if (profileType & inputDeviceTypes) {
break;
}
}
if ((profileType & inputDeviceTypes) == 0) {
continue;
}
sp inputDesc = new AudioInputDescriptor(inProfile);
inputDesc->mInputSource = AUDIO_SOURCE_MIC;
inputDesc->mDevice = profileType;
// find the address
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_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = inputDesc->mSamplingRate;
config.channel_mask = inputDesc->mChannelMask;
config.format = inputDesc->mFormat;
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(),
&input,
&config,
&inputDesc->mDevice,
address,
AUDIO_SOURCE_MIC,
AUDIO_INPUT_FLAG_NONE);
if (status == NO_ERROR) {
for (size_t k = 0; k < inProfile->mSupportedDevices.size(); k++) {
audio_devices_t type = inProfile->mSupportedDevices[k]->type();
ssize_t index =
mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
// give a valid ID to an attached device once confirmed it is reachable
if (index >= 0) {
sp devDesc = mAvailableInputDevices[index];
if (!devDesc->isAttached()) {
devDesc->attach(mHwModules[i]);
devDesc->importAudioPort(inProfile);
}
}
}
mpClientInterface->closeInput(input);
} else {
ALOGW("Cannot open input stream for device %08x on hw module %s",
inputDesc->mDevice,
mHwModules[i]->mName);
}
}
}
// make sure all attached devices have been allocated a unique ID
for (size_t i = 0; i < mAvailableOutputDevices.size();) {
if (!mAvailableOutputDevices[i]->isAttached()) {
ALOGW("Input 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 (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
}
ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
//通路打通之后更新路由策略对应的默认设备
updateDevicesAndOutputs();
#ifdef AUDIO_POLICY_TEST
if (mPrimaryOutput != 0) {
AudioParameter outputCmd = AudioParameter();
outputCmd.addInt(String8("set_id"), 0);
mpClientInterface->setParameters(mPrimaryOutput->mIoHandle, outputCmd.toString());
mTestDevice = AUDIO_DEVICE_OUT_SPEAKER;
mTestSamplingRate = 44100;
mTestFormat = AUDIO_FORMAT_PCM_16_BIT;
mTestChannels = AUDIO_CHANNEL_OUT_STEREO;
mTestLatencyMs = 0;
mCurOutput = 0;
mDirectOutput = false;
for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
mTestOutputs[i] = 0;
}
const size_t SIZE = 256;
char buffer[SIZE];
snprintf(buffer, SIZE, "AudioPolicyManagerTest");
run(buffer, ANDROID_PRIORITY_AUDIO);
}
#endif //AUDIO_POLICY_TEST
}
2.6 通过engineInstance这个静态实例进一步查询获取AudioPolicyManagerInterface类的一个实例,AudioPolicyManager类中变量mEngine是ManagerInterfaceImpl的实例,他是Engine的代理,AudioPolicyManager通过mEngine查询获取当前设备信息。路由策略的规则都在是Engine类中定义的
Engine::Engine()
: mManagerInterface(this),
mPhoneState(AUDIO_MODE_NORMAL),
mApmObserver(NULL)
{
for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
}
}
status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
switch(usage) {
case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO &&
config != AUDIO_POLICY_FORCE_NONE) {
ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
return BAD_VALUE;
}
mForceUse[usage] = config;
break;
case AUDIO_POLICY_FORCE_FOR_MEDIA:
if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP &&
config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE &&
config != AUDIO_POLICY_FORCE_NO_BT_A2DP && config != AUDIO_POLICY_FORCE_SPEAKER ) {
ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
return BAD_VALUE;
}
mForceUse[usage] = config;
break;
case AUDIO_POLICY_FORCE_FOR_RECORD:
if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
config != AUDIO_POLICY_FORCE_NONE) {
ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
return BAD_VALUE;
}
mForceUse[usage] = config;
break;
case AUDIO_POLICY_FORCE_FOR_DOCK:
if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK &&
config != AUDIO_POLICY_FORCE_BT_DESK_DOCK &&
config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) {
ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
}
mForceUse[usage] = config;
break;
case AUDIO_POLICY_FORCE_FOR_SYSTEM:
if (config != AUDIO_POLICY_FORCE_NONE &&
config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
}
mForceUse[usage] = config;
break;
case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
if (config != AUDIO_POLICY_FORCE_NONE &&
config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) {
ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config);
}
mForceUse[usage] = config;
break;
default:
ALOGW("setForceUse() invalid usage %d", usage);
break;
}
return NO_ERROR;
}
2.7 加载audio_policy.conf配置信息,audio_policy.conf文件中是预先根据平台特性设置好的音频信息,优先加载 /vendor/etc/audio_policy.conf,如果没有就加载/system/etc/audio_policy.conf
图(audio hw modules)
从图中看到音频硬件模块是如何划分的:primary硬件模块为出厂时就具备的音频设备,比如,speaker ,mic等等,a2db模块就是蓝牙设备,usb模块是通过usb输出音频信息的设备,r_submix模块为远程音频设备。各个硬件模块又细分输入输出通路,输入输出通路根据使用的硬件设备,支持的音频格式,采样率等信息,在规划具体的通路,比如primary硬件模块输出通路就规划了九条具体的通路,分析支持不同的应用场景。
AudioPolicyManager根据图(audio hw modules)的组织关系,将各个硬件模块封装成HwModule对象,将具体的通道封装成IoProfile对象,根据组织关系存储起来 。 audioPolicyServer这里所建立的通路都是控制通路,非数据通路。
2.8 完成audio_policy.conf信息的解析之后,就要进入实质性加载硬件设备的操作,根据mHwModules中保存硬件模块,分别加载图(audio hw modules)中primary,a2db,usb,r_submix设备,audiopolicyserver只下达加载操作,这些设备的具体加载过程由AudioFlinger完成,加载成功之后AudioFlinger会返回 audio_module_handle_t ,audiopolicyserver后期会通过这个module handle与audioflinger交互信息。
2.9 每个硬件模块包含多个输入输出通道,硬件模组加载成功之后,就要打通每条通道,并为每条通道设置默认device。mpClientInterface->openOutput ,mpClientInterface->openInput分别开启输出输入通路,这些通路的具体建立也是在audioflinger中完成的,通路建立完成之后,audioflinger返回audio_io_handle_t给audioPolicyServer,每一个io handle都对应一个thread,要么是PlaybackThread,要么是RecordThread,audioPolicyServer可以根据io handle找到具体thread实例
以上操作完成之后AudioPolicyManager调用updateDevicesAndOutputs更新每个路由策略的设备信息,保存在数组变量mDeviceForStrategy,后面的操作可直接获取当前路由策略下的具体device,完成路由选择工作。至此audioPolicyServer的初始化过程分析完毕。