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 的构造函数将

  1. 解析音频策略配置文件,从而获取到设备所支持的音频设备信息
    (包括设备是否支持 Offload、Direct 模式输出,各输入输出 profile 所支持的采样率、通道数、数据格式等),

  2. 加载全部 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录音线程。

在这里插入图片描述

发布了329 篇原创文章 · 获赞 66 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/Ciellee/article/details/101835510
今日推荐