Android audio(6)-audiopolicyservice介绍

发布于:2025-04-09 ⋅ 阅读:(38) ⋅ 点赞:(0)

AudioPolicyService 是策略的制定者,比如某种 Stream 类型不同设备的音量(index/DB)是多少、某种 Stream 类型的音频数据流对应什么设备等等。而 AudioFlinger 则是策略的执行者,例如具体如何与音频设备通信,维护现有系统中可用的音频设备,以及多个音频流的混音处理,音频数据流的算法处理(重采样,音效),音量调节,音频数据搬运等等都由它完成。

AudioPolicyService 根据用户配置来指导 AudioFlinger 加载设备接口,起到路由功能。在 Android Audio 系统中主要完成以下几个任务:
1)管理输入输出设备,包括设备的连接/断开状态,设备的选择和切换等
2)管理系统的音频策略,比如通话时播放音乐、或者播放音乐时来电话的一系列处理
3)管理系统的音量/静音
4)上层的一些音频参数也可以通过AudioPolicyService设置到底层
5)管理音效和流的配置

一、初始化

与AudioPolicyService 生命周期关联的有三个函数, 构造函数 AudioPolicyService、onFirstRef 和初始化有关, 析构函数 ~AudioPolicyService 和销毁有关。通过对android代码的学习,我们可以看到与成员变量相关的初始化都是 在构造函数里面做,而与业务相关的初始化都是在onFirstRef 里面完成。这是关注点分离思想的一种体现。

源码位置:/frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp

1、构造函数

AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService(), // 定义在IAudioPolicyService.h中, 作为Binder调用的Bn端
      mAudioPolicyManager(NULL),  // APM
      mAudioPolicyClient(NULL), 
      mPhoneState(AUDIO_MODE_INVALID), // 通话状态 
      mCaptureStateNotifier(false) {
}

2、onFirstRef

void AudioPolicyService::onFirstRef()
{
    {
        Mutex::Autolock _l(mLock);
        //一个系统的服务通常都需要线程去承载,不断处理命令。
        // 启动音频命令线程,audio命令相关,如音量控制、音频参数设置
        mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
        // 启动输出命令线程,Output管理
        mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
 
        mAudioPolicyClient = new AudioPolicyClient(this);
        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
    }
    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;
    }
    uidPolicy->registerSelf();
    sensorPrivacyPolicy->registerSelf();
}

可以看到这里创建了两个 AudioCommandThread 和 AudioPolicyManager,而在创建 AudioPolicyManager 时创建了AudioPolicyClient作为参数传入其中。

3、析构函数

AudioPolicyService::~AudioPolicyService()
{
    mAudioCommandThread->exit();
    mOutputCommandThread->exit();
 
    destroyAudioPolicyManager(mAudioPolicyManager);
    delete mAudioPolicyClient;
 
    mNotificationClients.clear();
    mAudioPolicyEffects.clear();
 
    mUidPolicy->unregisterSelf();
    mSensorPrivacyPolicy->unregisterSelf();
 
    mUidPolicy.clear();
    mSensorPrivacyPolicy.clear();
}

这里主要是做销毁,情基本是对初始化创建对象的回收。

二、AudioPolicyManager

AudioPolicyManager是 AudioPolicyService 服务进程下的功能模块,主要负责解析各种 Audio 配置 xml 文件,例如 audio_policy_configuration.xml 中音频的设备、流以及路由关系等。从audiopolicyservice和audiopolicymanager的设计我们可以学到,服务承载实体(进程,service等)可以和服务的业务逻辑代码分离!!!!! 服务实体是为了实现异步以及序列化操作

1、AudioPolicyManager创建
上面的代码可以看到 AudioPolicyManager 是在 AudioPolicyService 的 onFirstRef 中调用 createAudioPolicyManager() 方法创建的。传入参数为 new AudioPolicyClient(this)。这样audiopolicymanager就可以调用audiopolicyservice的接口。

createAudioPolicyManager

源码位置:/frameworks/av/services/audiopolicy/manager/AudioPolicyFactory.cpp

extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
    AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);
    status_t status = apm->initialize();
    if (status != NO_ERROR) {
        delete apm;
        apm = nullptr;
    }
    return apm;
}

AudioPolicyClient
AudioPolicyClient 类定义在 AudioPolicyService.h 中。源码位置:/frameworks/av/services/audiopolicy/service/AudioPolicyService.h

class AudioPolicyClient : public AudioPolicyClientInterface
{
public:
explicit AudioPolicyClient(AudioPolicyService *service) : mAudioPolicyService(service) {}

}

它的实现在 frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp 中。

AudioPolicyManager

源码位置:/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp

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() {
    // 处理音频配置xml
    if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
        ALOGE("无法加载音频策略配置文件,设置默认值");
        getConfig().setDefault();
    }
}

对于解析音频配置相关的 xml 文件我们会在后面单独分析。

三、Engine创建

Engine 是主要负责音频路由/音量相关的业务。Engine 的创建是在 AudioPolicyManager 的 initialize() 中。

status_t AudioPolicyManager::initialize() {
    {
        auto engLib = EngineLibrary::load("libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");
        ……
        mEngine = engLib->createEngine();
        ……
        mEngine->setObserver(this);
        status_t status = mEngine->initCheck();
        ……
    }
    ……
    return status;
}

EngineLibrary.cpp:createEngine
源码位置:/frameworks/av/services/audiopolicy/managerdefault/EngineLibrary.cpp

bool EngineLibrary::init(std::string libraryPath)
{
    ……
    mCreateEngineInstance = (EngineInterface* (*)())dlsym(mLibraryHandle, "createEngineInstance");
    ……
    return true;
 }
 
EngineInstance EngineLibrary::createEngine()
{
    if (mCreateEngineInstance == nullptr || mDestroyEngineInstance == nullptr) {
        return EngineInstance();
    }
    return EngineInstance(mCreateEngineInstance(),[lib = shared_from_this(), destroy = mDestroyEngineInstance] (EngineInterface* e) {
        destroy(e);
    });
}

EngineInstance .cpp:createEngineInstance
源码位置:/frameworks/av/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp

EngineInstance *EngineInstance::getInstance()
{
    static EngineInstance instance;
    return &instance;
}
 
Engine *EngineInstance::getEngine() const
{
    static Engine engine;
    return &engine;
}
 
template <>
EngineInterface *EngineInstance::queryInterface() const
{
    return getEngine()->queryInterface<EngineInterface>();
}
 
extern "C" EngineInterface* createEngineInstance()
{
    return audio_policy::EngineInstance::getInstance()->queryInterface<EngineInterface>();
}

在这里最后创建了 Engine。
Engine.cpp
源码位置:/frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp

Engine::Engine()
{
    auto result = EngineBase::loadAudioPolicyEngineConfig();
    auto legacyStrategy = getLegacyStrategy();
    for (const auto &strategy : legacyStrategy) {
        mLegacyStrategyMap[getProductStrategyByName(strategy.name)] = strategy.id;
    }
}

这里调用了一个比较重要的函数 loadAudioPolicyEngineConfig()。

EngineBase.cpp: loadAudioPolicyEngineConfig()

engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
{
    auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
    // 确保名称唯一
    LOG_ALWAYS_FATAL_IF(std::any_of(std::begin(volumeGroups), std::end(volumeGroups), [&volumeConfig](const auto &volumeGroup) {
        return volumeConfig.name == volumeGroup.second->getName(); }), "group name %s defined twice, review the configuration", volumeConfig.name.c_str());
 
        // 表示当前VolumeGroup还没有被加载过,开始创建加载
        sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin, volumeConfig.indexMax);
        volumeGroups[volumeGroup->getId()] = volumeGroup;
 
        for (auto &configCurve : volumeConfig.volumeCurves) {
            device_category deviceCat = DEVICE_CATEGORY_SPEAKER;
            if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {
                continue;
            }
            sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
            for (auto &point : configCurve.curvePoints) {
                curve->add({point.index, point.attenuationInMb});
            }
            volumeGroup->add(curve);
        }
        return volumeGroup;
    };
    auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {
        for (const auto &attr : group.attributesVect) {
            strategy->addAttributes({group.stream, volumeGroup->getId(), attr});
            volumeGroup->addSupportedAttributes(attr);
        }
    };
    auto checkStreamForGroups = [](auto streamType, const auto &volumeGroups) {
        const auto &iter = std::find_if(std::begin(volumeGroups), std::end(volumeGroups), [&streamType](const auto &volumeGroup) {
            const auto& streams = volumeGroup.second->getStreamTypes();
            return std::find(std::begin(streams), std::end(streams), streamType) != std::end(streams);
        });
        return iter != end(volumeGroups);
    };
 
    // 这里开始进行解析,最终会解析出来策略、标准、标准类型以及音量组四个内容
    auto result = engineConfig::parse();
    if (result.parsedConfig == nullptr) {
        // 如果上面没有解析没有找到配置,使用默认的配置
        engineConfig::Config config = gDefaultEngineConfig;
        android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
        result = {std::make_unique<engineConfig::Config>(config), static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
    }
    ……
    engineConfig::VolumeGroup defaultVolumeConfig;
    engineConfig::VolumeGroup defaultSystemVolumeConfig;
    // 循环解析所有的音量组
    for (auto &volumeConfig : result.parsedConfig->volumeGroups) {
        // 保存未在配置中定义的流的默认音量配置 将music和patch作为未定义流类型的默认配置
        if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {
            defaultVolumeConfig = volumeConfig;
        }
        if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {
            defaultSystemVolumeConfig = volumeConfig;
        }
        // 这里调用上面第一个lamabda表达式
        // 这里定义的mVolumeGroups是一个map容器,其中second是VolumeGroup指针,定义在VolumeGroup.h中
        // 这里调用这个lambda表达式是为了讲volumeConfig中包含的volumeGroups解析到mVolumeGroups中
        loadVolumeConfig(mVolumeGroups, volumeConfig);
    }
    // 循环遍历所有的音频策略
    for (auto& strategyConfig : result.parsedConfig->productStrategies) {
        sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
        // 查找该策略是否有相应的音量组
        for (const auto &group : strategyConfig.attributesGroups) {
            const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups), [&group](const auto &volumeGroup) {
                return group.volumeGroup == volumeGroup.second->getName(); 
            });
            sp<VolumeGroup> volumeGroup = nullptr;
            // 如果没有为此策略提供音量组,则使用音乐音量组配置创建一个新的音量组(视为默认设置) 
            if (iter == end(mVolumeGroups)) {
                engineConfig::VolumeGroup volumeConfig;
                if (group.stream >= AUDIO_STREAM_PUBLIC_CNT) {
                    volumeConfig = defaultSystemVolumeConfig;
                } else {
                    volumeConfig = defaultVolumeConfig;
                }
                volumeConfig.name = group.volumeGroup;
                volumeGroup = loadVolumeConfig(mVolumeGroups, volumeConfig);
            } else {
                volumeGroup = iter->second;
            }
            if (group.stream != AUDIO_STREAM_DEFAULT) {
                // 可以将旧流一次分组 
                LOG_ALWAYS_FATAL_IF(checkStreamForGroups(group.stream, mVolumeGroups), "stream %s already assigned to a volume group, " "review the configuration", toString(group.stream).c_str());
                volumeGroup->addSupportedStream(group.stream);
            }
            // 为策略添加相应的属性
            addSupportedAttributesToGroup(group, volumeGroup, strategy);
        }
        product_strategy_t strategyId = strategy->getId();
        mProductStrategies[strategyId] = strategy;
    }
    // 将新创建的strategy保存到mProductStrategies中并分配一个单独的ID
    mProductStrategies.initialize();
    return result;
}

总结

通过前面几篇文章的学习,我们也了解了音频服务初始化的大致流程,下面总结一下:

audioserver实例化audioflinger
audioserver实例化audiopolicyservice
audiopolicyservice创建audiopolicymanager
audiopolicymanager解析xml配置文件
audiopolicymanager创建engine
audiopolicymanager调用audioflinger接口打开audio interface
audiopolicymanager调用audioflinger接口打开音频通道(output,注意区分stream和output的概念)

经过上面的流程系统音频服务已经启动处于ready状态,如果有应用需要播放则会通过服务选择合适的硬件播出。


网站公告

今日签到

点亮在社区的每一天
去签到