分析Android O的AudioPolicyService服务(一)

AudioPolicyManager.cpp:音频策略的管理类,也可以说是服务端;
  • 分析createAudioPolicyManager函数的初始化;
void AudioPolicyService::onFirstRef()
{
.......
mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
......
}

createAudioPolicyManager函数在如下文件中进行声明和实现

路径:frameworks/av/services/audiopolicy/manager/AudioPolicyFactory.cpp

#include "managerdefault/AudioPolicyManager.h"

namespace android {

extern "C" AudioPolicyInterface* createAudioPolicyManager(
        AudioPolicyClientInterface *clientInterface)
{
    return new AudioPolicyManager(clientInterface);
}

extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
{
    delete interface;
}

} // namespace android

通过new 一个AudioPolicyManager对象,

路径:frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
        : AudioPolicyManager(clientInterface, false /*forTesting*/)
{
    loadConfig(); //加载音频的配置文件,配置文件在哪里呢?请看下面
    initialize(); //初始化对象
}
  • 接下来就看loadConfig()的函数中具体加载什么样的配置文件呢?
#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf

void AudioPolicyManager::loadConfig() {
#ifdef USE_XML_AUDIO_POLICY_CONF //如果这个宏在Android.mk文件中有定义则执行
    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();
    }
}

两个配置文件的宏定义如下:
frameworks/av/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h

/
//      Definitions for audio policy configuration file (audio_policy.conf)
/

#define AUDIO_HARDWARE_MODULE_ID_MAX_LEN 32

#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"

如果配置不存在,则加载默认的配置;

  • 第二函数就是initialize(),它做了哪些工作呢??
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
    //通过实例engineInstance查询AudioPolicyManagerInterface接口
    mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
    if (mEngine == NULL) {
        ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
        return NO_INIT;
    }
    // 将AudioPolicyManager设置观察者
    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
    //现在mAvailableOutputDevices和mAvailableInputDevices变量包含所有连接的设备
    //打开所有输出流必须能访问连接设备
    audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
    audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
    for (const auto& hwModule : mHwModulesAll) {
       ......
        //初始化所有的硬件模块
    }
    // open input streams needed to access attached devices to validate
    // mAvailableInputDevices list
    //使mAvailableInputDevices列表的设备生效
    for (const auto& inProfile : hwModule->getInputProfiles()) {
    }
    ......
    // make sure all attached devices have been allocated a unique ID
    // 保证所有的连接设备都有一个独一无二的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++;
    }
	// 保证所有输入连接设备都有一个独一无二的ID
    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);
            }
        }
    }
    //更新设备和输出设备,其实就是根据系统的当前状态选择最后的输出设备
    updateDevicesAndOutputs();
    return status;
}

至此初始化的任务就已经执行完毕,该函数整理来说干了四件事:
第一,获取AudioPolicyManagerInterface的引擎对象mEngine
第二,设置AudioPolicyManager的观察者,允许引擎可获取有关设备、流、hwmodules等集合的信息。
第三,打通音频的输出输入设备
第四,根据音频的输出输入设备类型的策略设置当前的路由策略

 

  • 下面来具体分析EngineInstance的实例对做了什么:
    // 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;
    }

通过命名空间的audio_policy得到EngineInstance单例类然后在通过getInstance()获取engineInstance的指针对象;
EngineInstance.cpp的类,路径:
frameworks/av/services/audiopolicy/enginedefault/src/EngineInstance.cpp

#include <AudioPolicyManagerInterface.h>
#include "AudioPolicyEngineInstance.h"
#include "Engine.h"

namespace android
{
namespace audio_policy //命名空间为audio_policy
{
//构造函数,没有做任何事情,因为是单例
EngineInstance::EngineInstance()
{
}
//返回EngineInstance对象的地址
EngineInstance *EngineInstance::getInstance()
{
    static EngineInstance instance;
    return &instance;
}
//返回Engine对象的地址,也就是指针
Engine *EngineInstance::getEngine() const
{
    static Engine engine;
    return &engine;
}
//模板函数,返回AudioPolicyManagerInterface对象的指针
template <>
AudioPolicyManagerInterface *EngineInstance::queryInterface() const
{
    return getEngine()->queryInterface<AudioPolicyManagerInterface>();
}

} // namespace audio_policy
} // namespace android

既然已经得到了单例,那么有什么作用???
作用就是通过queryInterface函数获取Engine对象指针,如上面的代码,这个Engine的作用就比较大了,稍后分析,
调用下面的代码,首先通过queryInterface函数获取mEngine对象指针,然后再设置AudioPolicyManagerObserver为作为观察者,最后,通过mEngine->initCheck()函数检测观察者模式是否设置成功;

// 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;
}

所有与音频策略相关的设置和获取都在Engine.cpp类中:
frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp

  • 再来分析音频设备:
    // 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;

首先从DeviceVector得到输入、输出的设备类型变量:
下面的这个for循环有点长,需要有点耐心:
 

//变量mHwModulesAll的声明在.h文件中:HwModuleCollection mHwModulesAll;
//开始循环遍历所有的音频模块,这些音频模块不一定每个都可用
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中,声明:HwModuleCollection mHwModules;这个变量只保存加载成功的音频硬件模块
    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()) {
        //得到InputProfileCollection实例,outProfile实质就是IOProfile对象的引用
        //判断输出设备是可以打开
        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;
        }
        //得到tts输出设备是否可用
        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;
        }
        //new 一个输出设备的描述符
        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;
            }
            //将输出设备添加到列表中mOutputs,然后设备输出设备
            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());
        }
    }
}

接下来就为可用的输入、输出设备分析独一无二的ID:

// make sure all attached devices have been allocated a unique ID
for (size_t i = 0; i  < mAvailableOutputDevices.size();) {
		//调用的路径:DeviceVector->DeviceDescriptor.h->AudioPort.h->isAttached()
		//判断是音频硬件模块是否真的可用
    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);
        }
    }
}
  • 最后一个方法:updateDevicesAndOutputs(),根据当前系统设备状态设置音频策略:
void AudioPolicyManager::updateDevicesAndOutputs()
{
    for (int i = 0; i < NUM_STRATEGIES; i++) {
    		//为设备获取音频策略
        mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/);
    }
    mPreviousOutputs = mOutputs;
}

至此分析完成,如有不正确的地方,请指教

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值