
开始这篇文章之前,可以先了解<Linux音频编程>
1. 架构在AndroID中,Audio整体架构如下
2. Java Audio在Java层把Audio从功能上分为三类接口
AudioService: 负责的是Audio系统的综合管理功能, 包括音量控制、音频IO设备的管理、音频焦点机制AudioTrack: 负责音频数据的输出,即播放AudioRecorder: 负责音频数据的输出和输入,即录制2.1 AudioService
AudioService由SystemServer启动,实现了IAudioService的Bn端;AudioManager则实现了IAudioService的Bp端
AudioService的功能实现依赖Java AudioSystem类,AudioSystem是Native AudioSystem在Java层的封装和代理
IAudioService - frameworks/base/media/java/androID/media/IAudioService.aIDl)
SystemServer::startOtherServices() SystemServiceManager::startService(AudioService.lifecycle.class) new AudioService() AudioService::onStart() publishBinderService(Context.AUdio_SERVICE, new AudioService()); // 向servicemanager注册服务 ServiceManager.addService( , , , ) AudioService::onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY) AudioService::systemReady() AudioHandler::handleMessage(MSG_SYstem_READY) AudioService::onSystemReady() AudioHandler::onLoadSoundEffects() // Bluetooth releated config AudioService::onIndicateSystemReady() // 位于androID_media_AudioSystem.cpp androID_media_AudioSystem_systemReady() // 位于AudioSystem.cpp AudioSystem::systemReady()
AudioTrack通过JNI的方式使用androID_media_AudioTrack.cpp封装的接口,进而使用到Native AudioTrack提供的接口
AudioRecord通过JNI的方式使用androID_media_AudioRecord.cpp封装的接口,进而使用到Native AudioRecord提供的接口
3. Native Audio3.1 audioserverNative Audio服务在AndroID N之前存在于mediaserver中,AndroID N之后由audioserver来启动
audioserver主要启动了两个Native binder服务
- audioflinger: 音频系统策略的执行者, 负责音频流设备的管理及音频流数据的处理传输, 由libaudioflinger实现具体功能- AudioPolicyService : 音频系统策略的制定者, 负责音频设备切换的策略抉择、音量调节策略等, 由libaudiopolicyservice实现具体功能
audioserver的启动的详细过程如下
/* * frameworks/av/media/audioserver/audioserver.rc */# cat audioserver.rcservice audioserver /system/bin/audioserver class core user audioserver onrestart restart vendor.audio-hal-2-0 onrestart restart audio-hal-2-0/* * Code: frameworks/av/media/audioserver/main_audioserver.cpp * Output: /system/bin/audioserver */main() audioflinger::instantiate() BinderService::instantiate() BinderService::publish() IServiceManager sm = defaultServiceManager() sm::addService("media.audio_flinger", new audioflinger()) audioflinger::onFirstRef() new PatchPanel(this) gaudioflinger = this; AudioPolicyService::instantiate() sm::addService("media.audio_policy", new AudioPolicyService()) AudioPolicyService::onFirstRef() // Tone播放线程 new AudioCommandThread("ApmTone", this) AudioCommandThread::onFirstRef() Thread::run() AudioCommandThread::threadLoop() // Audio命令线程 new AudioCommandThread("ApmAudio", this) // 输出命令线程 new AudioCommandThread("ApmOutput", this) new AudioPolicyClIEnt(this) createAudioPolicyManager() new AudioPolicyManager(mAudioPolicyClIEnt) AudioPolicyManager::AudioPolicyManager() /* * 当定义了USE_XML_AUdio_POliCY_CONF = 1 * 加载/odm/etc/audio_policy_configuration.xml * /vendor/etc/audio_policy_configuration.xml * /system/etc/audio_policy_configuration.xml * 否则加载 * /system/etc/audio_policy.conf * /vendor/etc/audio_policy.conf */ AudioPolicyManager::loadConfig() deserializeAudioPolicyXmlConfig() // FIXME: Do a lot of things AudioPolicyManager::initialize() new AudioPolicyEffects() new UIDPolicy(this) UIDPolicy::registerSelf() // Oboe Service AAudioService::instantiate() SoundTriggerHwService::instantiate()3.2 audioflingeraudioflinger实现了名为”media.audio_flinger”的binder本地端,而远程端由libaudioclIEnt的Iaudioflinger实现。
// 接口定义frameworks/av/include/media/Iaudioflinger.h // 实现audioflinger本地端libaudioflinger <==> frameworks/av/services/audioflinger/* // 实现audioflinger远程端libaudioclIEnt <==> frameworks/av/media/libaudioclIEnt/*
audioflinger主要提供了如下接口
在AudioFliger中,将DeviceHalinterface抽象为AudioHwDevice(音频设备)和AudioStreamOut(音频输出流)
3.3 AudioPolicyServiceAudioPolicyService实现了名为”media.audio_policy”的binder本地端,而远程端由libaudioclIEnt的IAudioPolicyService实现。
// 接口定义frameworks/av/include/media/IAudioPolicyService.h// 实现AudioPolicyService本地端libaudiopolicyservice <==> frameworks/av/services/audiopolicy/* // 实现AudioPolicyService远程端libaudioclIEnt <==> frameworks/av/media/libaudioclIEnt/*
AudioPolicyService主要提供了如下接口
3.4 libaudioclIEntlibaudioclIEnt实现了audioflinger和AudioPolicyService的远程端,并实现了如下接口供media JNI使用
// androID::media::* <===> frameworks/av/media/libaudioclIEnt/// JNI <===> frameworks/base/core/jni-----------------------------------------------------| androID::media::* | JNI |-----------------------------------------------------| AudioSystem.cpp | androID_media_AudioSystem.cpp || AudioRecord.cpp | androID_media_AudioRecord.cpp || AudioTrack.cpp | androID_media_AudioTrack.cpp |-----------------------------------------------------3.5 AAudio
AAudio是在AndroID O版本中引入的全新AndroID C API。此API专为需要低延迟的高性能音频应用而设计。应用通过读取数据并将数据写入流来与AAudio进行通信。
// 接口定义frameworks/av/media/libaaudio/include/aaudio/AAudio.h// 实现AAudio服务libaaudioservice <==> frameworks/av/services/oboeservice/*// 实现AAudio客户端libaaudio <==> frameworks/av/media/libaaudio/*4. Audio HAL
Audio HAL架构比较复杂,混合了HIDL和Legacy HAL,目前已经有一套成熟的框架
可参考<Android O Treble架构下Hal进程启动及HIDL服务注册过程>
对厂商来说,实现以so库的方式音频接口,并在音频政策配置文件(audio_policy_configuration.xml)进行配置,系统就会自动加载对应音频设备
4.1 音频接口HAL接口定义在harDWare/libharDWare/include/harDWare/audio.h文件中
- audio_hw_device: 音频设备- audio_stream_out: 输出流- audio_stream_in: 输入流- audio_stream: 音频流
下面是当前已经实现或可参考的音频设备
默认主设备: harDWare/libharDWare/modules/audio车载主设备: device/generic/car/emulator/audio/driverUSB设备: harDWare/libharDWare/modules/usbaudioRemoteSubmix设备: harDWare/libharDWare/modules/audio_remote_submix蓝牙A2DP设备: system/bt/audio_a2dp_hw4.2 HAL接口
Audio HAL接口(以2.0为例)是对音频接口的进一步抽象
// 音频设备IDevice.hal |- initCheck() |- setMasterVolume(float): 设置除voice call外其他音频活动的音量 |- getMasterVolume(): 获取主音量 |- setMicMute(bool): 设置麦克风静音状态 |- getMicMute(): 获取麦克风静音状态 |- setMasterMute(bool): 设置静音状态 |- getMasterMute(bool): 获取静音状态 |- getinputBufferSize(AudioConfig): 获取音频输入缓冲区大小 |- openOutputStream(*): 创建和打开音频硬件输出流 |- openinputStream(*): 创建和打开音频硬件输入流 |- supportsAudioPatches(): 判断HAL是否支持AudioPatch |- createAudioPatch(*): 为SRC和SINK创建AudioPatch |- releaseAudioPatch(*): 释放一个AudioPatch |- getAudioPort(*): 获取指定音频端口属性 |- setAudioPortConfig(*): 配置音频端口 |- getHwAvSync(): 获取设备的硬件同步源 |- setScreenState(bool): 设置屏幕状态 |- getParameters(vec<string>): 获取厂商定义的参数值 |- setParameters(vec<ParameterValue>): 设置厂商定义的参数值// 音频代理IDevicesFactory.hal |- openDevice(Device): 打开一个音频设备// 主音频设备IPrimaryDevice.hal |- setMasterVolume(float): 设置voice call音量 |- setMode(AudioMode): 设置音频模式 |- getBtScoNrecEnabled(): 获取蓝牙ECNR使能状态 |- setBtScoNrecEnabled(): 设置蓝牙ECNR使能状态 |- getBtScoWIDebandEnabled(): 获取蓝牙WIDeband使能状态 |- setBtScoWIDebandEnabled(bool): 设置蓝牙WIDeband使能状态 |- getTtyMode(): 获取当前TTY模式 |- setTtyMode(): 设置当前TTY模式 |- getHacEnabled(): 获取HearingAID使能状态 |- setHacEnabled(): 设置HearingAID使能状态// 音频流IStream.hal |- getFrameSize(): 获取帧大小 |- getFrameCount(): 获取缓冲区帧数 |- getBufferSize(): 获取流的缓冲区大小 |- getSampleRate(): 获取采样率(Hz) |- getSupportedSampleRates(): 获取流支持的支持的采样率(Hz) |- setSampleRate(uint32_t): 设置流的采样率 |- getChannelMask(): 获取流的channel mask |- getSupportedChannelMasks(): 获取流支持的channel mask |- setChannelMask(): 获取流的channel mask |- getFormat(): 获取流的音频格式 |- getSupportedFormats(): 获取流支持的音频格式 |- setFormat(): 设置流的音频格式 |- getAudioPropertIEs(): 获取流参数 |- addEffect(): 添加音效到流 |- removeEffect(uint64_t): 从流上停止某音效 |- standby(uint64_t): 让硬件输入输出进入standby模式 |- getDevice(): 获取流连接的设备 |- setDevice(): 连接设置到流 |- setConnectedState(): 通知设备连接状态 |- setHwAvSync(AudioHwSync): 设置硬件同步源 |- getParameters(vec<string>): 获取厂商参数 |- setParameters(vec<ParameterValue>): 设置厂商参数 |- start(): 开始流 *** 作(mmap模式) |- stop(): 停止流 *** 作 |- createmmapBuffer(): 获取audio mmap缓冲区信息 |- getMmapposition(): 读取audio mmap缓冲区读写位置 |- close(): 关闭和释放流// 音频输入流IStreamIn.hal |- getAudioSource(): 获取输入流的source描述 |- setGain(): 设置音频驱动的输入增益 |- prepareForReading(): 设置必需的传输层以从驱动接收音频缓冲区 |- getinputFramesLost(): 获取丢失的输入帧的数量 |- getCaptureposition(): 获取接收到的音频帧数与时钟时间。// 音频输出流IStreamOut.hal |- getLatency(): 获取硬件传输延迟(毫秒) |- setVolume(float, float): 设置音量, 用于混音后 |- prepareForWriting(): 设置必需的传输层将音频缓冲区传递给驱动 |- getRenderposition(): 获取音频DSP写入DAC的音频帧数 |- getNextWriteTimestamp(): 获取下一次写入音频驱动时间(微秒) |- setCallback(): 设置回调接口, 用于非阻塞模式 |- clearCallback(): 清楚回调 |- supportsPauseAndResume(): HAL是否支持暂停和恢复流 |- pause(): 暂停流 |- resume(): 恢复流 |- supportsDrain(): ??? |- drain(): ??? |- flush(): 刷新流 |- getPresentationposition(): 获取音频帧数// 音频输入流回调IStreamOutCallback.hal |- onWriteReady(): 非阻塞写入已完成 |- onDrainReady(): Drain(?)完成 |- one rror(): 出错4.3 HAL服务
Audio HAL服务对HAL接口和音频接口进行了HIDL方式地封装
/* * Code: harDWare/interfaces/audio/common/all-versions/default/service/service.cpp * Output: /vendor/bin/hw/androID.harDWare.audio@2.0-service */main() // 连接至vndservicemanager androID::Processstate::initWithDriver("/dev/vndbinder") androID::Processstate::self()->startThreadPool() registerPassthroughServiceImplementation<audio::V4_0::IDevicesFactory>() registerPassthroughServiceImplementation<audio::V2_0::IDevicesFactory>() registerPassthroughServiceImplementation<audio::effect::V4_0::IEffectsFactory>() registerPassthroughServiceImplementation<audio::effect::V2_0::IEffectsFactory>() registerPassthroughServiceImplementation<soundtrigger::V2_1::ISoundTriggerHw>() registerPassthroughServiceImplementation<soundtrigger::V2_0::ISoundTriggerHw>() registerPassthroughServiceImplementation<bluetooth::a2dp::V1_0::IBluetoothAudioOffload>() androID::harDWare::joinRpcThreadpool()# cat /vendor/etc/init/androID.harDWare.audio@2.0-service.rcservice vendor.audio-hal-2-0 /vendor/bin/hw/androID.harDWare.audio@2.0-service class hal user audioserver oneshot interface androID.harDWare.audio@4.0::IDevicesFactory default interface androID.harDWare.audio@2.0::IDevicesFactory default# /vendor/etc/vintf/manifest.xml<manifest version="1.0" type="device" target-level="3">... <hal format="hIDl"> <name>androID.harDWare.audio</name> <transport>hwbinder</transport> <version>4.0</version> <interface> <name>IDevicesFactory</name> <instance>default</instance> </interface> </hal>...</manifest>4.4 libaudiohallibaudiohal封装了audio hal的接口,以libaudiohal.so的形式供audioflinger使用,而libaudiohal又使用了libaudiohal@4.0和libaudiohal@2.0两个库,同时libaudiohal@4.0和libaudiohal@2.0又分别是audio hal接口的封装
libaudiohal最终提供的是DeviceHalinterface、DevicesFactoryHalinterface和EffectsFactoryHalinterface接口
# tree frameworks/av/media/libaudiohal.+--- 2.0| +--- AndroID.bp -- libaudiohal@2.0+--- 4.0| +--- AndroID.bp -- libaudiohal@4.0+--- AndroID.bp -- libaudiohal/* * DevicesFactoryHalinterface提供了create和openDevice两个方法 */DevicesFactoryHalinterface::create() /* * 这里仅仅分析了V2_0版本, V4_0类似 * 提供了两种方式来访问audio harDWare * - HIDL: 即DevicesFactoryHalHIDl, 用于primary, usb和remote_submix * - Legacy: 即DevicesFactoryHalLocal, 用于a2dp */ new DevicesFactoryHalHybrID() new DevicesFactoryHalLocal() new DevicesFactoryHalHIDl() harDWare::audio::V2_0::IDevicesFactory::getService()DevicesFactoryHalinterface::openDevice(char *name, DeviceHalinterface *device) DevicesFactoryHalHybrID::openDevice(name, device) // 针对hearing_aID和a2dp设备 DevicesFactoryHalLocal::openDevice(name, device) load_audio_interface(name, audio_hw_device_t **dev) new DeviceHalLocal(dev) // 针对其他设备, 包括primary, usb, remote_submix设备 DevicesFactoryHalHIDl::openDevice(name, device) // 获取HIDL接口名 nameFromHal(name, IDevicesFactory::Device &) IDevicesFactory::openDevice() new DeviceHalHIDl(IDevice)/* 这里暂不做分析 */EffectsFactoryHalinterface::create()
参考:
<Android音频>
以上是内存溢出为你收集整理的Android Audio介绍全部内容,希望文章能够帮你解决Android Audio介绍所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)