目录
- 背景
- 概念
- [Android Audio调用流程(app-framework-HAL)](#Android Audio调用流程(app-framework-HAL))
-
- [标记0 libaudioclient](#标记0 libaudioclient)
-
- [标记1 libaudioclient :aps变量赋值](#标记1 libaudioclient :aps变量赋值)
-
- [标记1.1 binder变量赋值](#标记1.1 binder变量赋值)
- [标记2 audiopolicy](#标记2 audiopolicy)
-
- [标记4 audiopolicy:mAudioPolicyManager变量赋值](#标记4 audiopolicy:mAudioPolicyManager变量赋值)
- [标记5 audiopolicy](#标记5 audiopolicy)
-
- [标记6 audiopolicy:mpClientInterface变量赋值](#标记6 audiopolicy:mpClientInterface变量赋值)
- [标记7 audiopolicy](#标记7 audiopolicy)
- [标记8 audiopolicy](#标记8 audiopolicy)
- [标记10 audioflinger](#标记10 audioflinger)
-
- [标记11 audioflinger:hwDevice变量赋值](#标记11 audioflinger:hwDevice变量赋值)
- [标记12 audioflinger](#标记12 audioflinger)
-
- [标记12.1 hardware:load_audio_interface](#标记12.1 hardware:load_audio_interface)
- [标记13 hardware](#标记13 hardware)
- dumpsys调试
背景
平台:Android 14
在设备开机的过程中,需要设置用户关机前的音量,因此在开机时可获取当前音量值去设置某个端口的音量增益,来达到设备开机后的音量记忆。
概念
进入代码分析之前,重温一下平时设置的音量1-100和音量增益(Volume Gain)的关系,有助于更好理解Android音量设置原理。
平时在音频设备或软件中设置的音量(比如1-100的范围)通常是一个相对的量度,用于提供给用户一个直观的方式来控制音频输出的响度。这个音量设置并不直接对应于特定的分贝值,而是根据设备的硬件或软件配置来确定增益的大小。
以下是音量设置与增益关系的一般概念:
- 相对刻度 :
- 音量滑块或旋钮上的1-100通常表示一个从非常安静到非常响亮的相对刻度。
- 音量增益通常以分贝(dB)为单位进行度量,分贝是一个比例单位。具体的分贝值取决于系统的参考音量级别和增益范围。
- 线性关系 :
- 在某些系统中,音量和增益可能呈线性关系,这意味着音量的每次增加或减少对应相同的分贝数。
- 例如,音量每增加10,增益增加1 dB。
- 对数关系 :
- 更常见的是,音量和增益之间存在对数关系,以模拟人耳对声音的感知。
- 在对数刻度中,音量的增加不是均匀的,而是随着音量级别的增加而增加的。
- 系统校准 :
- 音频系统通常会在校准过程中确定1-100音量级别与增益之间的确切映射。
- 这涉及到设置参考音量(通常是0 dBFS,即满刻度信号)和最大音量对应的最大增益。
- 最大音量与增益 :
- 最大音量(例如100)通常对应于系统能够安全输出的最大增益,而不会引起失真。
- 这个最大增益可能是在特定音量级别下不会失真的最高分贝数。
- 最小音量与增益 :
- 最小音量(例如1)则对应于系统可以输出的最小增益,仍然保持可听见的水平。
- 这通常远高于0 dB SPL,因为人耳的听觉阈值非常低。
- 中间音量级别 :
- 中间的音量级别(例如50)通常对应于系统增益的中间点,提供平衡的听感。
- 设备差异 :
- 不同的音频设备和软件可能会有不同的音量和增益映射方式。
- 音量标准化 :
- 有些系统可能会采用音量标准化技术,以确保不同音量级别下的音频输出保持一致的响度。
Android Audio调用流程(app-framework-HAL)
先上图
应用调用setStreamVolume函数设置音量后会调用mAudioManager.setAudioPortGain来设置硬件增益,达到设备开机后的音量增益记忆。
frameworks/base/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@Override
public void setStreamVolume(float volume) throws RemoteException {
synchronized (mImplLock) {
if (mReleased) {
throw new IllegalStateException("Device already released.");
}
mSourceVolume = volume;
//查看updateAudioConfigLocked实现
updateAudioConfigLocked();
}
}
private float getMediaStreamVolume() {
return (float) mCurrentIndex / (float) mCurrentMaxIndex;
}
private void updateAudioConfigLocked() {
float volume = mSourceVolume * getMediaStreamVolume();
//转换应用层的音量为音量增益(单位db)
gainValue += sourceGain.stepValue() * (int) (volume * steps + 0.5);
......
// size of gain values is 1 in MODE_JOINT
int[] gainValues = new int[] { gainValue };
sourceGainConfig = sourceGain.buildConfig(AudioGain.MODE_JOINT,
sourceGain.channelMask(), gainValues, 0);
......
//调用audio硬件设置音量增益
mAudioManager.setAudioPortGain(mAudioSource, sourceGainConfig);
}
frameworks/base/media/java/android/media/AudioManager.java
/**
* Set the gain on the specified AudioPort. The AudioGainConfig config is build by
* AudioGain.buildConfig()
* @hide
*/
public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
if (port == null || gain == null) {
return ERROR_BAD_VALUE;
}
//调用port对象的activeConfig()方法,获取当前活动的音频端口配置。
AudioPortConfig activeConfig = port.activeConfig();
//使用AudioPortConfig构造函数创建一个新的音频端口配置对象config。
AudioPortConfig config = new AudioPortConfig(port, activeConfig.samplingRate(),
activeConfig.channelMask(), activeConfig.format(), gain);
//设置config对象的mConfigMask字段为AudioPortConfig.GAIN。
//这指定了配置掩码,表明只更改增益设置,而不是其他配置如采样率、声道掩码或格式。
config.mConfigMask = AudioPortConfig.GAIN;
//应用新的音频端口配置
return AudioSystem.setAudioPortConfig(config);
}
frameworks/base/media/java/android/media/AudioSystem.java
//由native 关键字可知使用了本地方法实现函数
public static native int setAudioPortConfig(AudioPortConfig config);
frameworks/base/core/jni/android_media_AudioSystem.cpp
{"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
(void *)android_media_AudioSystem_setAudioPortConfig},
......
static jint
android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
jobject jAudioPortConfig)
{
ALOGV("setAudioPortConfig");
if (jAudioPortConfig == NULL) {
return AUDIO_JAVA_BAD_VALUE;
}
//确认jAudioPortConfig是一个正确的AudioPortConfig类的实例,如果不是,返回错误码
if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
return AUDIO_JAVA_BAD_VALUE;
}
//定义一个本地audio_port_config结构体实例,用于存储转换后的本地音频端口配置。
struct audio_port_config nAudioPortConfig = {};
//调用convertAudioPortConfigToNative函数,将Java层的AudioPortConfig对象转换为本地的audio_port_config结构体。
//返回值jStatus用于检查转换是否成功。
jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
//调用AudioSystem::setAudioPortConfig方法,传入本地音频端口配置,以应用配置。
//标记0
status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
//将本地状态码status转换为Java可以理解的状态码jStatus。
//返回Java层,这样Java层就可以知道操作是否成功或出现了什么错误。
jStatus = nativeToJavaStatus(status);
return jStatus;
}
标记0 libaudioclient
frameworks/av/media/libaudioclient/AudioSystem.cpp
status_t AudioSystem::setAudioPortConfig(const struct audio_port_config* config) {
if (config == nullptr) {
return BAD_VALUE;
}
//获取音频策略服务的引用(IAudioPolicyService是一个接口,用于与音频策略服务进行交互)
//标记1
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
//将传入的audio_port_config结构转换为AIDL(Android Interface Definition Language)格式的AudioPortConfigFw对象。
//VALUE_OR_RETURN_STATUS是一个宏或模板函数,用于检查转换操作是否成功,并可能返回一个错误状态码。
media::AudioPortConfigFw configAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_config_AudioPortConfigFw(*config));
//标记2
return statusTFromBinderStatus(aps->setAudioPortConfig(configAidl));
}
标记1 libaudioclient :aps变量赋值
aps的赋值为AudioPolicyService地址指针
frameworks/av/media/libaudioclient/AudioSystem.cpp
// establish binder interface to AudioPolicyService
const sp<IAudioPolicyService> AudioSystem::get_audio_policy_service() {
sp<IAudioPolicyService> ap;
sp<AudioPolicyServiceClient> apc;
{
//创建一个自动锁_l,它在作用域开始时自动加锁,并在作用域结束时自动解锁,用于保护临界区代码。
//gLockAPS是全局的互斥锁,用于同步对共享资源的访问。
Mutex::Autolock _l(gLockAPS);
//检查gAudioPolicyService是否已初始化。如果不为null,表示服务连接已建立,可直接返回服务接口。
if (gAudioPolicyService == 0) {
//如果服务尚未连接,它会使用defaultServiceManager()获取系统服务管理器的句柄,并尝试检索"media.audio_policy"服务。如服务未立即可用,它将每半秒重试一次,直到服务出现。
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
//标记1.1
binder = sm->getService(String16("media.audio_policy"));
if (binder != 0)
break;
ALOGW("AudioPolicyService not published, waiting...");
usleep(500000); // 0.5 s
} while (true);
if (gAudioPolicyServiceClient == NULL) {
//创建AudioPolicyServiceClient客户端,用于接收来自AudioPolicyService的回调通知
gAudioPolicyServiceClient = new AudioPolicyServiceClient();
}
binder->linkToDeath(gAudioPolicyServiceClient);
//将binder转换为IAudioPolicyService接口,以便通过定义好的接口与服务交互。
gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
LOG_ALWAYS_FATAL_IF(gAudioPolicyService == 0);
apc = gAudioPolicyServiceClient;
// Make sure callbacks can be received by gAudioPolicyServiceClient
ProcessState::self()->startThreadPool();
}
ap = gAudioPolicyService;
}
//返回IAudioPolicyService接口指针,使得调用者能够与音频策略服务进行互动。
return ap;
}
标记1.1 binder变量赋值
binder 变量获取的是media.audio_policy 服务
和media.audio_flinger 服务不一样
在ServiceManager进程中添加media.audio_flinger服务
frameworks/av/services/audioflinger/AudioFlinger.cpp
void AudioFlinger::instantiate() {
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
new AudioFlingerServerAdapter(new AudioFlinger()), false,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
}
frameworks/av/media/libaudioclient/include/media/IAudioFlinger.h
class IAudioFlinger : public virtual RefBase {
static constexpr char DEFAULT_SERVICE_NAME[] = "media.audio_flinger";
}
标记2 audiopolicy
在AudioPolicyService.cpp中没有setAudioPortConfig函数的具体实现,需要查找哪些文件包含了AudioPolicyService.h,并实现了setAudioPortConfig函数。查看发现AudioPolicyInterfaceImpl.cpp(实现的是 StatusAudioPolicyService::setAudioPortConfig(constmedia::AudioPortConfigFw&configAidl)
)、AudioPolicyClientImpl.cpp(实现的是 AudioPolicyService::AudioPolicyClient::setAudioPortConfig
),因此查看AudioPolicyInterfaceImpl.cpp中的实现,由此可以AudioPolicyInterfaceImpl实现了AudioPolicyService.中的一部分函数
frameworks/av/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp //实现了AudioPolicyService.中的一部分函数
#include "AudioPolicyService.h"
Status AudioPolicyService::setAudioPortConfig(const media::AudioPortConfigFw& configAidl)
{
audio_port_config config = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPortConfigFw_audio_port_config(configAidl));
RETURN_IF_BINDER_ERROR(
binderStatusFromStatusT(AudioValidator::validateAudioPortConfig(config)));
......
//标记4 mAudioPolicyManager的赋值 //标记5
return binderStatusFromStatusT(mAudioPolicyManager->setAudioPortConfig(&config));
}
标记4 audiopolicy:mAudioPolicyManager变量赋值
mAudioPolicyManager的赋值为AudioPolicyManager
frameworks/av/services/audiopolicy/service/AudioPolicyService.h
AudioPolicyInterface *mAudioPolicyManager;
frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
void AudioPolicyService::onFirstRef()
{
......
{
......
mAudioPolicyClient = new AudioPolicyClient(this);
loadAudioPolicyManager();
//标记4.1 传入AudioPolicyClient实例
mAudioPolicyManager = mCreateAudioPolicyManager(mAudioPolicyClient);
}
......
}
static const char kAudioPolicyManagerCustomPath[] = "libaudiopolicymanagercustom.so";
void AudioPolicyService::loadAudioPolicyManager()
{
//使用dlopen函数打开一个动态链接库(.so文件),这里指定了库文件的路径kAudioPolicyManagerCustomPath和加载时的属 性RTLD_NOW(立即加载)。mLibraryHandle是AudioPolicyService类中的成员变量,用于存储打开的动态链接库的句柄
mLibraryHandle = dlopen(kAudioPolicyManagerCustomPath, RTLD_NOW);
if (mLibraryHandle != nullptr) {
ALOGI("%s loading %s", __func__, kAudioPolicyManagerCustomPath);
mCreateAudioPolicyManager = reinterpret_cast<CreateAudioPolicyManagerInstance>
(dlsym(mLibraryHandle, "createAudioPolicyManager"));
}
}
AudioPolicyService::AudioPolicyService()
//使用列表初始化(冒号:)来初始化继承自基类的成员。
//这里BnAudioPolicyService()是基类构造函数的调用,
//表示AudioPolicyService继承自BnAudioPolicyService。
: BnAudioPolicyService(),
......
//mCreateAudioPolicyManager是类成员变量,这里被初始化为createAudioPolicyManager,
//它是一个函数或函数指针,用于创建音频策略管理器实例。
mCreateAudioPolicyManager(createAudioPolicyManager),
......
}
//标记4.1传入参数new AudioPolicyClient的地址
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
//此处就是标记4中mAudioPolicyManager的地址指向
AudioPolicyManager *apm = new AudioPolicyManager(
config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
clientInterface);
status_t status = apm->initialize();
......
return apm;
}
标记5 audiopolicy
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.h
//AudioPolicyManager 继承 AudioPolicyInterface
class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManagerObserver
{
virtual status_t setAudioPortConfig(const struct audio_port_config *config);
AudioPolicyClientInterface *mpClientInterface;
}
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config)
{
sp<AudioPortConfig> audioPortConfig;
......
struct audio_port_config backupConfig = {};
status_t status = audioPortConfig->applyAudioPortConfig(config, &backupConfig);
if (status == NO_ERROR) {
struct audio_port_config newConfig = {};
audioPortConfig->toAudioPortConfig(&newConfig, config);
//标记6 mpClientInterface赋值 //标记7
status = mpClientInterface->setAudioPortConfig(&newConfig, 0);
}
return status;
}
标记6 audiopolicy:mpClientInterface变量赋值
mpClientInterface变量的赋值AudioPolicyClient实例:
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
AudioPolicyManager::AudioPolicyManager(const sp<const AudioPolicyConfig>& config,
EngineInstance&& engine,
AudioPolicyClientInterface *clientInterface)
:
mUidCached(AID_AUDIOSERVER), // no need to call getuid(), there's only one of us running.
mConfig(config),
//在此处赋值,clientInterface是函数指针,在标记4.1中new AudioPolicyManager实例化传入了clientInterface参数new AudioPolicyClient的地址
mpClientInterface(clientInterface),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
{
}
也就是下面函数
frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
AudioPolicyManager *apm = new AudioPolicyManager(
config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
clientInterface);
status_t status = apm->initialize();
......
return apm;
}
AudioPolicyService::AudioPolicyService()
//使用列表初始化(冒号:)来初始化继承自基类的成员。
//这里BnAudioPolicyService()是基类构造函数的调用,
//表示AudioPolicyService继承自BnAudioPolicyService。
: BnAudioPolicyService(),
//mCreateAudioPolicyManager是类成员变量,这里被初始化为createAudioPolicyManager,
//它是一个函数或函数指针,用于创建音频策略管理器实例。
mCreateAudioPolicyManager(createAudioPolicyManager),
}
void AudioPolicyService::onFirstRef()
{
{
mAudioPolicyClient = new AudioPolicyClient(this);
loadAudioPolicyManager();
//传入AudioPolicyClient实例
mAudioPolicyManager = mCreateAudioPolicyManager(mAudioPolicyClient);
}
static const char kAudioPolicyManagerCustomPath[] = "libaudiopolicymanagercustom.so";
void AudioPolicyService::loadAudioPolicyManager()
{
//使用dlopen函数打开一个动态链接库(.so文件),这里指定了库文件的路径kAudioPolicyManagerCustomPath和加载时的属 性RTLD_NOW(立即加载)。mLibraryHandle是AudioPolicyService类中的成员变量,用于存储打开的动态链接库的句柄
mLibraryHandle = dlopen(kAudioPolicyManagerCustomPath, RTLD_NOW);
if (mLibraryHandle != nullptr) {
ALOGI("%s loading %s", __func__, kAudioPolicyManagerCustomPath);
mCreateAudioPolicyManager = reinterpret_cast<CreateAudioPolicyManagerInstance>
(dlsym(mLibraryHandle, "createAudioPolicyManager"));
}
}
标记7 audiopolicy
AudioPolicyClient继承AudioPolicyClientInterface
frameworks/av/services/audiopolicy/service/AudioPolicyService.h
class AudioPolicyClient : public AudioPolicyClientInterface{
/* Set audio port configuration */
virtual status_t setAudioPortConfig(const struct audio_port_config *config, int delayMs);
}
搜索AudioPolicyClient::setAudioPortConfig函数,发现函数实现在下面路径
frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp
status_t AudioPolicyService::AudioPolicyClient::setAudioPortConfig(
const struct audio_port_config *config,
int delayMs)
{
return mAudioPolicyService->clientSetAudioPortConfig(config, delayMs);
}
frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config,
int delayMs)
{
return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
}
status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand(
const struct audio_port_config *config, int delayMs)
{
sp<AudioCommand> command = new AudioCommand();
//设置需要传入队列的命令
command->mCommand = SET_AUDIOPORT_CONFIG;
SetAudioPortConfigData *data = new SetAudioPortConfigData();
data->mConfig = *config;
command->mParam = data;
command->mWaitStatus = true;
ALOGV("AudioCommandThread() adding set port config delay %d", delayMs);
//将一个音频命令对象按照指定的延迟时间加入到执行队列,并等待命令执行完成或超时
//此处发送 SET_AUDIOPORT_CONFIG 音频命令到队列
//标记8
return sendCommand(command, delayMs);
}
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
Mutex::Autolock _l(mLock);
//调用insertCommand_l成员函数,将传入的command和delayMs插入到线程的命令队列中。
//insertCommand_l是一个私有成员函数,负责将命令插入到一个按时间排序的队列中。
insertCommand_l(command, delayMs);
//mWaitWorkCV是条件变量,用于在有工作可做时通知等待的线程。
//signal函数唤醒等待条件变量的线程,告知有新的命令可以处理。
mWaitWorkCV.signal();
}
return command->mStatus;
}
标记8 audiopolicy
将一个音频命令对象加入到执行队列等待命令执行完成或超时。因此可以搜索命令SET_AUDIOPORT_CONFIG,看在什么位置进行了处理。
frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
bool AudioPolicyService::AudioCommandThread::threadLoop()
{
switch (command->mCommand) {
......
case SET_AUDIOPORT_CONFIG: {
SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set port config");
//标记9 af获取到AudioFlinger服务
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == 0) {
command->mStatus = PERMISSION_DENIED;
} else {
mLock.unlock();
//标记10
command->mStatus = af->setAudioPortConfig(&data->mConfig);
mLock.lock();
}
} break;
......
标记10 audioflinger
因此在AudioFlinger.cpp文件中调用setAudioPortConfig
frameworks/av/services/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::setAudioPortConfig(const struct audio_port_config *config)
{
......
audio_module_handle_t module;
if (config->type == AUDIO_PORT_TYPE_DEVICE) {
module = config->ext.device.hw_module;
} else {
module = config->ext.mix.hw_module;
}
......
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(index);
//使用HAL间接操作audio硬件
//标记11 hwDevice赋值 //标记13
return audioHwDevice->hwDevice()->setAudioPortConfig(config);
}
frameworks/av/services/audioflinger/AudioHwDevice.h
sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
标记11 audioflinger:hwDevice变量赋值
hwDevice类型为sp <DeviceHalInterface>
,在标记12中查询到hwDevice最终赋值为DeviceHalLocal的实例地址
frameworks/av/services/audioflinger/AudioHwDevice.h
sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
//mHwDevice值是在初始化时传入进来的,因此需要找到实例化的地方
AudioHwDevice(audio_module_handle_t handle,
const char *moduleName,
const sp<DeviceHalInterface>& hwDevice,
Flags flags)
: mHandle(handle)
, mModuleName(strdup(moduleName))
//初始化时传入参数
, mHwDevice(hwDevice)
, mFlags(flags) { }
正好在AudioFlinger.cpp有new AudioHwDevice在标记14位置
frameworks/av/services/audioflinger/AudioFlinger.cpp
......
mDevicesFactoryHal = DevicesFactoryHalInterface::create();
......
// loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
AudioHwDevice* AudioFlinger::loadHwModule_l(const char *name){
sp<DeviceHalInterface> dev;
//打开一个指定名称的音频设备,并获取该设备的智能指针引用
//标记12 调用到DevicesFactoryHal的openDevice方法打开驱动设备
int rc = mDevicesFactoryHal->openDevice(name, &dev);
......
//标记14
AudioHwDevice *audioDevice = new AudioHwDevice(handle, name, dev, flags);
}
标记12 audioflinger
mDevicesFactoryHal的赋值最终调用DevicesFactoryHalLocal,最终差查询到 标记11中类型为sp <DeviceHalInterface>
的hwDevice,最终传入了 DeviceHalLocal的实例地址
frameworks/av/services/audioflinger/AudioFlinger.cpp
mDevicesFactoryHal = DevicesFactoryHalInterface::create();
frameworks/av/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h //由libaudiohal可知HAL实现在hardware
class DevicesFactoryHalInterface : public RefBase
{
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device) = 0;
}
hardware/amlogic/audio/utils/hidl_interface_7_0/impl/DevicesFactoryHalLocal.h
//DevicesFactoryHalLocal 继承DevicesFactoryHalInterface,因此可以查看DevicesFactoryHalLocal 的实现
class DevicesFactoryHalLocal : public DevicesFactoryHalInterface{
......
}
hardware/amlogic/audio/utils/hidl_interface_7_0/impl/DevicesFactoryHalLocal.cpp
status_t DevicesFactoryHalLocal::openDevice(const char *name, sp<DeviceHalInterface> *device) {
audio_hw_device_t *dev;
//标记12.1 加载音频设备模块
status_t rc = load_audio_interface(name, &dev);
if (rc == OK) {
//标记11中类型为sp <DeviceHalInterface>的hwDevice,最终传入了 DeviceHalLocal的实例地址
*device = new DeviceHalLocal(dev);
}
return rc;
}
标记12.1 hardware:load_audio_interface
load_audio_interface获取对应音频模块
hardware/amlogic/audio/utils/hidl_interface_7_0/impl/DevicesFactoryHalLocal.cpp
//其中load_audio_interface中可以查看到需要获取哪个硬件的模块ID AUDIO_HARDWARE_MODULE_ID
static status_t load_audio_interface(const char *if_name, audio_hw_device_t **dev)
{
//搜索 AUDIO_HARDWARE_MODULE_ID 可以得到很多硬件音频模块USB、远程音频等,找到我们需要的aml即可
//利用HAL层注册信息id和name,获取相应的模块
//主要用于id相同、name不同,即获取相同功能但厂家不同的硬件库。
//获取到HAL层音频模块后,再将mod通过audio_hw_device_open打开
rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
//调用对应音频模块的open方法
rc = audio_hw_device_open(mod, dev);
}
其中 audio_hw_device_open
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,
TO_HW_DEVICE_T_OPEN(device));//调用硬件模块的open方法
}
搜索 AUDIO_HARDWARE_MODULE_ID 可以得到很多硬件音频模块USB、远程音频等,找到我们需要的aml即可
/hardware/amlogic/audio/audio_hal/audio_hw.c
static struct hw_module_methods_t hal_module_methods = {
.open = adev_open,
};
struct audio_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = AUDIO_MODULE_API_VERSION_0_1,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "aml audio HW HAL",
.author = "amlogic, Corp.",
.methods = &hal_module_methods,
},
};
static int adev_open(const hw_module_t* module, const char* name, hw_device_t** device){
struct aml_audio_device *adev;
//注意该结构体,hw_device后的函数就是对应framework的接口,=后的函数就是对应hal的接口
adev->hw_device.set_audio_port_config = adev_set_audio_port_config;
}
static int adev_set_audio_port_config(struct audio_hw_device *dev, const struct audio_port_config *config)
{
AM_LOGI("id:%d, dev:%s, role:%s, type:%s, gain:%d", config->id, ....)
}
标记13 hardware
frameworks/av/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h //由libaudiohal可知HAL实现在hardware
{
virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
}
/hardware/amlogic/audio/utils/hidl_interface_7_0/impl/DeviceHalLocal.h
#include <media/audiohal/DeviceHalInterface.h>
class DeviceHalLocal : public DeviceHalInterface{
virtual status_t setAudioPortConfig(const struct audio_port_config *config);
}
hardware/amlogic/audio/utils/hidl_interface_7_0/impl/DeviceHalLocal.cpp
status_t DeviceHalLocal::setAudioPortConfig(const struct audio_port_config *config) {
if (version() >= AUDIO_DEVICE_API_VERSION_3_0)
return mDev->set_audio_port_config(mDev, config);
else
return INVALID_OPERATION;
}
dumpsys调试
dumpsys 关于音量的有下面三种属性:
media.audio_flinger、audio、media.audio_policy
其中media.audio_flinger能显示关与aml中关于HAL的信息
static IBinder getAudioFlinger() {
return ServiceManager.getService("media.audio_flinger");
}