Android 音频源码分析——AudioFlinger
Posted VNanyesheshou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 音频源码分析——AudioFlinger相关的知识,希望对你有一定的参考价值。
Android 音频源码分析——AndroidRecord录音(一)
Android 音频源码分析——AndroidRecord录音(二)
Android 音频源码分析——AndroidRecord音频数据传输流程
Android 音频源码分析——audioserver启动
Android 音频源码分析——AudioFlinger
Android 音频源码分析——AudioTrack设备选择
源码基于Android9.0
混音:把多种来源的声音,整合至一个立体音轨或单音轨中。
AudioFlinger和AudioPolicyService是音频中的两大服务,这里先整理下AudioFlinger。
AudioPolicyService时策略制定者,不和AudioHal直接交互;而AudioFlinger是策略执行者,与AudioHal层进行交互。
简介
AudioFlinger运行在audioserver进程中,是一个音频服务。主要职责:
- 音频数据接收和转发,录音时从HAL层获取音频数据,转给客户端;播放时从客户端获取数据,并发送给HAL层。
- 音频数据处理,包括数据格式转换、声道数转换、重采样、混音、音效、变速、音量等。
- 执行AudioFlinger的策略。
与HAL层通信
framework层hidl相关代码目录: frameworks/av/media/libaudiohal
hal层hidl相关代码: hardware/interfaces/audio
AudioFlinger通过hidl接口的方式调用hal层服务。有上一篇文章可知,启动AudioPolicyService时,会加载音频配置文件,然后根据配置加载HAL module。后续可以调用hal接口进行其他交互(设备选择、通路、读写数据等)。
AudioPolicyService并不直接于Hal层交互,而是由AudioFlinger和Hal通信,这里看看AudioFlinger加载音频模块。
1 加载Module
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
if (name == NULL)
return AUDIO_MODULE_HANDLE_NONE;
if (!settingsAllowed())
return AUDIO_MODULE_HANDLE_NONE;
Mutex::Autolock _l(mLock);
return loadHwModule_l(name);
// loadHwModule_l() must be called with AudioFlinger::mLock held
audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
sp<DeviceHalInterface> dev;
int rc = mDevicesFactoryHal->openDevice(name, &dev);
//......
audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
return handle;
加载hal层module,mAudioHwDevs保存handle 和AudioHwDevice.
接着看mDevicesFactoryHal->openDevice流程
mDevicesFactoryHal->openDevice(name, &dev);
>>DevicesFactoryHalHybrid::openDevice
>>
status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device)
if (mDevicesFactory == 0) return NO_INIT;
IDevicesFactory::Device hidlDevice;
status_t status = nameFromHal(name, &hidlDevice);
if (status != OK) return status;
Result retval = Result::NOT_INITIALIZED;
Return<void> ret = mDevicesFactory->openDevice(
hidlDevice,
[&](Result r, const sp<IDevice>& result)
retval = r;
if (retval == Result::OK)
*device = new DeviceHalHidl(result);
);
if (ret.isOk())
if (retval == Result::OK) return OK;
else if (retval == Result::INVALID_ARGUMENTS) return BAD_VALUE;
else return NO_INIT;
return FAILED_TRANSACTION;
- nameFromHal通过name获取Device类型:IDevicesFactory::Device::PRIMARY、IDevicesFactory::Device::A2DP、IDevicesFactory::Device::USB、IDevicesFactory::Device::R_SUBMIX等;
- mDevicesFactory->openDevice通过hidl跨进程调用接口
hardware/interfaces/audio/core/all-versions/default/include/core/all-version/DevicesFactory.impl.h
Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb)
switch (device)
case IDevicesFactory::Device::PRIMARY:
return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
case IDevicesFactory::Device::A2DP:
return openDevice(AUDIO_HARDWARE_MODULE_ID_A2DP, _hidl_cb);
case IDevicesFactory::Device::USB:
return openDevice(AUDIO_HARDWARE_MODULE_ID_USB, _hidl_cb);
case IDevicesFactory::Device::R_SUBMIX:
return openDevice(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, _hidl_cb);
case IDevicesFactory::Device::STUB:
return openDevice(AUDIO_HARDWARE_MODULE_ID_STUB, _hidl_cb);
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
return Void();
int DevicesFactory::loadAudioInterface(const char* if_name, audio_hw_device_t** dev)
const hw_module_t* mod;
int rc;
rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
if (rc)
ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID,
if_name, strerror(-rc));
goto out;
rc = audio_hw_device_open(mod, dev);
if (rc)
ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID,
if_name, strerror(-rc));
goto out;
if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN)
ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
rc = -EINVAL;
audio_hw_device_close(*dev);
goto out;
return OK;
out:
*dev = NULL;
return rc;
- hw_get_module_by_class动态链接 hal 库,如:audio.primary.default.so、audio.a2dp.default.so、audio.usb.default.so
- audio_hw_device_open对应module method->open函数
2 open stream
这里看看加载后的openOutput流程
status_t AudioFlinger::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)
if (devices == NULL || *devices == AUDIO_DEVICE_NONE)
return BAD_VALUE;
Mutex::Autolock _l(mLock);
sp<ThreadBase> thread = openOutput_l(module, output, config, *devices, address, flags);
//......
return NO_INIT;
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t devices,
const String8& address,
audio_output_flags_t flags)
AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
//......
AudioStreamOut *outputStream = NULL;
status_t status = outHwDev->openOutputStream(
&outputStream,
*output,
devices,
flags,
config,
address.string());
mHardwareStatus = AUDIO_HW_IDLE;
if (status == NO_ERROR)
if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)
sp<MmapPlaybackThread> thread =
new MmapPlaybackThread(this, *output, outHwDev, outputStream,
devices, AUDIO_DEVICE_NONE, mSystemReady);
mMmapThreads.add(*output, thread);
return thread;
else
sp<PlaybackThread> thread;
if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
|| !isValidPcmSinkFormat(config->format)
|| !isValidPcmSinkChannelMask(config->channel_mask))
thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
else
thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
mPlaybackThreads.add(*output, thread);
return thread;
return 0;
- findSuitableHwDev_l找寻对应的AudioHwDevice;
- openOutputStream打开输出Stream,这里会调用到hal层 adev_open_output_stream中,这里就不分析了;
- 根据flags创建不同的通路线程;
- 将线程添加到mPlaybackThreads;
openinput 流程就先不分析了。
与APP通信
App和AudioFlinger间音频数据则通过共享内存的方式进行传输。
如下图AudioRecord的数据传输:
如下图AudioTrack的数据传输:
AudioFlinger是一个binder服务,app中的native层可以通过获取其binder服务从而进行交互。
如下示例:
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
record = audioFlinger->createRecord(input,
output,
&status);
以上是关于Android 音频源码分析——AudioFlinger的主要内容,如果未能解决你的问题,请参考以下文章
Android 音频源码分析——AudioTrack设备选择