Audio System 八 之 AudioPolicyService
十三、深入剖析Android音频之AudioPolicyService
AudioPolicyService是策略的制定者,比如什么时候打开音频接口设备、某种Stream类型的音频对应什么设备等等。
而AudioFlinger则是策略的执行者,例如具体如何与音频设备通信,如何维护现有系统中的音频设备,以及多个音频流的混音如何处理等等都得由它来完成。
AudioPolicyService根据用户配置来指导AudioFlinger加载设备接口,起到路由功能
Audio Service 启动过程:
[->\frameworks\av\media\audioserver\main_audioserver.cpp]
int main(int argc __unused, char **argv)
{
......
if (doLog && (childPid = fork()) != 0) {
......
} else {
// all other services
if (doLog) {
prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent media.log dies before me, kill me also
setpgid(0, 0); // but if I die first, don't kill my parent
}
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
RadioService::instantiate();
SoundTriggerHwService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
}
AudioPolicyService继承了模板类BinderService,该类用于注册native service。
BinderService是一个模板类,该类的publish函数就是完成向ServiceManager注册服务。
[->\frameworks\av\services\audiopolicy\service\AudioPolicyService.h]
static const char *getServiceName() ANDROID_API { return "media.audio_policy"; }
AudioPolicyService注册名为”media.audio_policy”的服务。
首先看看AudioPolicyService的onFirstRef()函数
[->\frameworks\av\services\audiopolicy\service\AudioPolicyService.cpp]
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
{
}
void AudioPolicyService::onFirstRef()
{
{
Mutex::Autolock _l(mLock);
/* Step 1:创建AudioCommandThread线程 */
// 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
// 使用老版本的 audio policy 初始化方式
....
#else
// 使用最新的 audio policy 初始化方式
ALOGI("AudioPolicyService CSTOR in new mode");
/* Step 2:创建AudioPolicyClient、 AudioPolicyManager */
mAudioPolicyClient = new AudioPolicyClient(this);
mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
#endif
}
// load audio processing modules
sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
{
Mutex::Autolock _l(mLock);
mAudioPolicyEffects = audioPolicyEffects;
}
}
先看看总体时序图:
13.1 创建AudioCommandThread线程
在AudioPolicyService对象构造过程中,分别创建了ApmTone、ApmAudio、ApmOutput三个AudioCommandThread线程:
1、ApmTone 用于播放 tone 音;
2、ApmAudio 用于执行 audio 命令;
3、ApmOutput 用于执行输出命令;
在第一次强引用 AudioCommandThread 线程对象时,AudioCommandThread 的 onFirstRef函数被回调,
在此启动线程
[->\frameworks\av\services\audiopolicy\service\AudioPolicyService.cpp]
void AudioPolicyService::AudioCommandThread::onFirstRef()
{
run(mName.string(), ANDROID_PRIORITY_AUDIO);
}
这里采用异步方式来执行audio command,
当需要执行上表中的命令时,首先将命令投递到 AudioCommandThread 的 mAudioCommands 命令向量表中,
然后通过mWaitWorkCV.signal()唤醒AudioCommandThread线程,
被唤醒的AudioCommandThread线程执行完command后,
又通过mWaitWorkCV.waitRelative(mLock, waitTime)睡眠等待命令到来。
13.2 创建AudioPolicyClient、 AudioPolicyManager
首先创建AudioPolicyClient
其 class 类定义如下:
[->\frameworks\av\services\audiopolicy\service\AudioPolicyService.h]
class AudioPolicyClient : public AudioPolicyClientInterface
{
public:
AudioPolicyClient(AudioPolicyService *service) : mAudioPolicyService(service) {}
virtual ~AudioPolicyClient() {}
// loads a HW module.
virtual audio_module_handle_t loadHwModule(const char *name);
......
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
uint32_t *latencyMs,
audio_output_flags_t flags);
......
// opens an audio input
virtual audio_io_handle_t openInput(audio_module_handle_t module,
audio_io_handle_t *input,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
audio_source_t source,
audio_input_flags_t flags);
......
private:
AudioPolicyService *mAudioPolicyService;
};
createAudioPolicyManager() 函数的实现位于
frameworks/av/services/audiopolicy/manager/AudioPolicyFactory.cpp文件中。
查看源码后我们会发现它实际上是直接调用了 AudioPolicyManager 的构造函数。
代码如下:
[->\frameworks\av\services\audiopolicy\manager\AudioPolicyFactory.cpp]
extern "C" AudioPolicyInterface* createAudioPolicyManager(
AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManager(clientInterface);
}
13.3 创建AudioPolicyManager()
总体流程图:
AudioPolicyManager 的构造函数将
-
解析音频策略配置文件,从而获取到设备所支持的音频设备信息
(包括设备是否支持 Offload、Direct 模式输出,各输入输出 profile 所支持的采样率、通道数、数据格式等), -
加载全部 HwModule,为之创建所有非 direct 输出类型的 outputStream 和所有 inputStream,
并创建相应的 playbackThread 或 recordThread 线程。
需要注意的是,Android 7.0上的音频策略配置文件开始使用 XML 格式,其文件名为 audio_policy_configuration.xml,
而在之前的版本上音频策略配置文件为 audio_policy.conf。
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp 中
AudioPolicyManager 构造函数的关键代码如下:
[->\frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp]
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
:
#ifdef AUDIO_POLICY_TEST
Thread(false),
#endif //AUDIO_POLICY_TEST
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false)
{
....
#ifdef USE_XML_AUDIO_POLICY_CONF
// 设备使用的配置文件为 audio_policy_configuration.xml
mVolumeCurves = new VolumeCurvesCollection();
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled,
static_cast<VolumeCurvesCollection *>(mVolumeCurves));
PolicySerializer serializer;
// 解析 xml 配置文件,将设备支持的音频输出设备保存在 mAvailableOutputDevices 变量中,
// 将设备支持的音频输入设备保存在 mAvailableInputDevices 变量中,将设备的默认音频输出
// 设备保存在 mDefaultOutputDevice 变量中。
if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) {
#else
// 设备使用的配置文件为 audio_policy.conf
mVolumeCurves = new StreamDescriptorCollection();
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled);
// 优先解析 vendor 目录下的 conf 配置文件,然后解析 device 目录下的 conf 配置文件。
// 将设备支持的音频输出设备保存在 mAvailableOutputDevices 变量中,
// 将设备支持的音频输入设备保存在 mAvailableInputDevices 变量中,将设备的默认音频输出
// 设备保存在 mDefaultOutputDevice 变量中。
if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
(ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
#endif
ALOGE("could not load audio policy configuration file, setting defaults");
config.setDefault();
}
// must be done after reading the policy (since conditionned by Speaker Drc Enabling)
mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled); // 设置音量调节曲线
....
// 依次加载 HwModule 并打开其所含 profile 的 outputStream 及 inputStream
for (size_t i = 0; i < mHwModules.size(); i++) {
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());
if (mHwModules[i]->mHandle == 0) {
ALOGW("could not open HW module %s", mHwModules[i]->getName());
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
// 打开当前 module 下所有非 direct 类型 profile 的 outputStream
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j];
....
// 如果当前操作的 module.profile 是 direct 类型,则不为其打开 outputStream
if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
continue;
}
....
// 获取采样率、通道数、数据格式等各音频参数
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("");
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;
// 为当前 module.profile 打开对应的 outputStream 并创建 playbackThread 线程
status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
&output,
&config,
&outputDesc->mDevice,
address,
&outputDesc->mLatency,
outputDesc->mFlags);
....
}
// open input streams needed to access attached devices to validate
// mAvailableInputDevices list
// 打开当前 module 下所有 profile 的 inputStream
for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)
{
const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
....
sp<AudioInputDescriptor> inputDesc =
new AudioInputDescriptor(inProfile);
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;
// 为当前 module.profile 打开对应的 inputStream 并创建 recordThread 线程
status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(),
&input,
&config,
&inputDesc->mDevice,
address,
AUDIO_SOURCE_MIC,
AUDIO_INPUT_FLAG_NONE);
....
}
}
....
updateDevicesAndOutputs(); // 更新系统缓存的音频输出设备信息
....
}
AudioPolicyManager对象构造过程中主要完成以下几个步骤:
1、 加载audio_policy_configuration.xml或者audio_policy.conf配置文件
2、 初始化音量调节点initializeVolumeCurves(speakerDrcEnabled)
3、 加载audio policy硬件抽象库:mpClientInterface->loadHwModule(mHwModules[i]->mName)
4、 打开对应的outputStream和inputStream : mpClientInterface->openOutput()、mpClientInterface->openInput
5、 更新系统缓存的音频输出设备信息updateDevicesAndOutputs()
13.3.1 加载audio_policy_configuration.xml或者audio_policy.conf配置文件
audio_policy_configuration.xml
audio_policy.conf同时定义了多个audio 接口,每一个audio 接口包含若干output和input,
而每个output和input又同时支持多种输入输出模式,每种输入输出模式又支持若干种设备。
13.3.2 初始化音量调节点initializeVolumeCurves(speakerDrcEnabled)
在AudioPolicyManagerBase中定义了音量调节对应的音频流描述符数组:
//audio_policy_volumes.xml
const AudioPolicyManagerBase::VolumeCurvePoint
*AudioPolicyManagerBase::sVolumeProfiles[AudioSystem::NUM_STREAM_TYPES]
[AudioPolicyManagerBase::DEVICE_CATEGORY_CNT] = {
{ // AUDIO_STREAM_VOICE_CALL
sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
sDefaultVoiceVolumeCurve // DEVICE_CATEGORY_EARPIECE
},
{ // AUDIO_STREAM_SYSTEM
sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
sDefaultSystemVolumeCurve // DEVICE_CATEGORY_EARPIECE
},
......
}
initializeVolumeCurves()函数就是初始化该数组元素:
[->]
void AudioPolicyManagerBase::initializeVolumeCurves()
{
for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
mStreams[i].mVolumeCurve[j] =
sVolumeProfiles[i][j];
}
}
// Check availability of DRC on speaker path: if available, override some of the speaker curves
if (mSpeakerDrcEnabled) {
mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = sDefaultSystemVolumeCurveDrc;
mStreams[AUDIO_STREAM_RING].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = sSpeakerSonificationVolumeCurveDrc;
mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = sSpeakerSonificationVolumeCurveDrc;
mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = sSpeakerSonificationVolumeCurveDrc;
}
}
13.3.3 加载audio policy硬件抽象库loadHwModule()
我们直接分析 AudioFlinger::loadHwModule_l() 中的 load_audio_interface() 函数
static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
{
const hw_module_t *mod;
int rc;
//根据名字加载audio_module模块
rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
ALOGE_IF(rc, "%s couldn't load audio hw module %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
//打开audio_device设备
rc = audio_hw_device_open(mod, dev);
ALOGE_IF(rc, "%s couldn't open audio hw device in %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
return 0;
}
[->\frameworks\av\services\audioflinger\AudioFlinger.cpp]
static inline int audio_hw_device_open(const struct hw_module_t* module, struct audio_hw_device** device)
{
return module->methods->open(module, AUDIO_HARDWARE_INTERFACE, (struct hw_device_t**)device);
}
[->\hardware\libhardware_legacy\audio\audio_hw_hal.cpp]
static int legacy_adev_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
struct legacy_audio_device *ladev;
int ret;
ladev = (struct legacy_audio_device *)calloc(1, sizeof(*ladev));
ladev->device.common.tag = HARDWARE_DEVICE_TAG;
ladev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
ladev->device.common.module = const_cast<hw_module_t*>(module);
ladev->device.common.close = legacy_adev_close;
ladev->device.init_check = adev_init_check;
ladev->device.set_voice_volume = adev_set_voice_volume;
ladev->device.set_master_volume = adev_set_master_volume;
ladev->device.get_master_volume = adev_get_master_volume;
ladev->device.set_mode = adev_set_mode;
ladev->device.set_mic_mute = adev_set_mic_mute;
ladev->device.get_mic_mute = adev_get_mic_mute;
ladev->device.set_parameters = adev_set_parameters;
ladev->device.get_parameters = adev_get_parameters;
ladev->device.get_input_buffer_size = adev_get_input_buffer_size;
ladev->device.open_output_stream = adev_open_output_stream;
ladev->device.close_output_stream = adev_close_output_stream;
ladev->device.open_input_stream = adev_open_input_stream;
ladev->device.close_input_stream = adev_close_input_stream;
ladev->device.dump = adev_dump;
ladev->hwif = createAudioHardware();
*device = &ladev->device.common;
return 0;
}
到此就加载完系统定义的所有音频接口,并生成相应的数据对象,如下图所示:’
13.3.4 打开对应的outputStream和inputStream
前面一小节已经分析过outputStream,这里不再分析了
打开音频输出后,在AudioFlinger与AudioPolicyService中的表现形式如下:
打开音频输入:
打开音频输入后,在AudioFlinger与AudioPolicyService中的表现形式如下:
13.3.5 更新系统缓存的音频输出设备信息updateDevicesAndOutputs()
[->\frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp]
void AudioPolicyManager::updateDevicesAndOutputs()
{
for (int i = 0; i < NUM_STRATEGIES; i++) {
mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/);
}
mPreviousOutputs = mOutputs;
}
13.4 总结
- 打开音频输出时创建一个audio_stream_out通道,并创建AudioStreamOut对象以及新建PlaybackThread播放线程。
- 打开音频输入时创建一个audio_stream_in通道,并创建AudioStreamIn对象以及创建RecordThread录音线程。