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), // APMmAudioPolicyClient(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() {// 處理音頻配置xmlif (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中并分配一個單獨的IDmProductStrategies.initialize();return result;
}
總結
通過前面幾篇文章的學習,我們也了解了音頻服務初始化的大致流程,下面總結一下:
audioserver實例化audioflinger
audioserver實例化audiopolicyservice
audiopolicyservice創建audiopolicymanager
audiopolicymanager解析xml配置文件
audiopolicymanager創建engine
audiopolicymanager調用audioflinger接口打開audio interface
audiopolicymanager調用audioflinger接口打開音頻通道(output,注意區分stream和output的概念)
經過上面的流程系統音頻服務已經啟動處于ready狀態,如果有應用需要播放則會通過服務選擇合適的硬件播出。