Android11 AudioTrack 创建过程

Android 系统播放声音,需要创建AudioTrack来和AudioFlinger通信,其创建过程如下
在这里插入图片描述

  1. 根据传入的声音属性得到output
  2. 通过得到的output,找到播放线程
  3. AudioFlinger在播放线程内,创建Track,和AudioTrack对应。后续通过它们进行通信

接下来分别看下其过程

找到output
在getOutputForAttr函数内,直接调用getOutputForAttrInt函数

//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::getOutputForAttrInt(
        audio_attributes_t *resultAttr,
        audio_io_handle_t *output,
        audio_session_t session,
        const audio_attributes_t *attr,
        audio_stream_type_t *stream,
        uid_t uid,
        const audio_config_t *config,
        audio_output_flags_t *flags,
        audio_port_handle_t *selectedDeviceId,
        bool *isRequestedDeviceForExclusiveUse,
        std::vector<sp<AudioPolicyMix>> *secondaryMixes,
        output_type_t *outputType)
{
	DeviceVector outputDevices;
    const audio_port_handle_t requestedPortId = *selectedDeviceId;
    DeviceVector msdDevices = getMsdAudioOutDevices();
    const sp<DeviceDescriptor> requestedDevice =
        mAvailableOutputDevices.getDeviceFromId(requestedPortId);

    *outputType = API_OUTPUT_INVALID;
    status_t status = getAudioAttributes(resultAttr, attr, *stream);//将attr赋值给resultAttr
	
	//省略
	outputDevices = mEngine->getOutputDevicesForAttributes(*resultAttr, requestedDevice, false);//根据resultAttr,找到device
	
	//省略
	if (*output == AUDIO_IO_HANDLE_NONE) {
        *output = getOutputForDevices(outputDevices, session, *stream, config,
                flags, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);//根据device,找到output
    }
	//省略
}

1,找到device

//frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp
DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
                                                   const sp<DeviceDescriptor> &preferredDevice,
                                                   bool fromCache) const
{
   
    product_strategy_t strategy = getProductStrategyForAttributes(attributes);
   	//省略
    return fromCache? mDevicesForStrategies.at(strategy) : getDevicesForProductStrategy(strategy);
}

首先,通过声音属性,从mProductStrategies中找到strategy,然后根据strategy,找到对应的device。getDevicesForProductStrategy这个函数由厂商自定义,修改声音的音频策略,大多数情况下可以修改这个函数。

2,根据device,找到output

//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
audio_io_handle_t AudioPolicyManager::getOutputForDevices(
        const DeviceVector &devices,
        audio_session_t session,
        audio_stream_type_t stream,
        const audio_config_t *config,
        audio_output_flags_t *flags,
        bool forceMutingHaptic)
{
	//省略
	if (audio_is_linear_pcm(config->format)) {
      
        SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);

        *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
        output = selectOutput(outputs, *flags, config->format, channelMask, config->sample_rate);
    }
  
    return output;

}

mOutputs中,支持该device的output可能有多个,通过getOutputsForDevices把它们找出来,然后调用selectOutput从中选择一个最符合的。怎么从中找到最合适的output,可以看其注释

	// select one output among several that provide a path to a particular device or set of
    // devices (the list was previously build by getOutputsForDevices()).
    // The priority is as follows:
    // 1: the output supporting haptic playback when requesting haptic playback
    // 2: the output with the highest number of requested functional flags
    // 3: the output supporting the exact channel mask
    // 4: the output with a higher channel count than requested
    // 5: the output with a higher sampling rate than requested
    // 6: the output with the highest number of requested performance flags
    // 7: the output with the bit depth the closest to the requested one
    // 8: the primary output
    // 9: the first output in the list

综上,找到output的流程为: audio_attributes_t >>> strategy >>> device >>> output

找到播放线程

AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
{
    return mPlaybackThreads.valueFor(output).get();
}

根据output,从mPlaybackThreads中找到对应的播放线程

创建Track

//frameworks/av/services/audioflinger/Threads.cpp
sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(/*省略*/)
{
	//省略
	 track = new Track(this, client, streamType, attr, sampleRate, format,
                          channelMask, frameCount,
                          nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
                          sessionId, creatorPid, uid, *flags, TrackBase::TYPE_DEFAULT, portId,
                          SIZE_MAX /*frameCountToBeReady*/, opPackageName);

   		//省略
        mTracks.add(track);

	//省略
}

AudioFlinger的PlaybackThread中有一个mTracks数组,先创建Track,然后将该Track保存到mTracks中。

总结
应用程序创建AudioTrack,导致在对应的播放线程内,创建Track和其对应。如何找到对应的播放线程?

  1. 根据传入的声音属性,找到strategy
  2. 根据strategy ,找到device
  3. 根据device找到output
  4. 根据output,从mPlaybackThreads中找到对应的播放线程
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值