Android O Audio libaudiohal模块分析

Android O Audio模块,多了一个libaudiohal文件夹:

Android.mk                DeviceHalLocal.h             DevicesFactoryHalLocal.h  EffectHalHidl.h             EffectsFactoryHalLocal.h  StreamHalLocal.cpp
ConversionHelperHidl.cpp  DevicesFactoryHalHidl.cpp    EffectBufferHalHidl.cpp   EffectHalLocal.cpp          HalDeathHandlerHidl.cpp   StreamHalLocal.h
ConversionHelperHidl.h    DevicesFactoryHalHidl.h      EffectBufferHalHidl.h     EffectHalLocal.h            include                   StreamPowerLog.h
DeviceHalHidl.cpp         DevicesFactoryHalHybrid.cpp  EffectBufferHalLocal.cpp  EffectsFactoryHalHidl.cpp   OWNERS
DeviceHalHidl.h           DevicesFactoryHalHybrid.h    EffectBufferHalLocal.h    EffectsFactoryHalHidl.h     StreamHalHidl.cpp
DeviceHalLocal.cpp        DevicesFactoryHalLocal.cpp   EffectHalHidl.cpp         EffectsFactoryHalLocal.cpp  StreamHalHidl.h

很明显,是给hidl准备的.

我们来研究研究怎么个用法.

Audio播放的时候都需要先openOutput.我们就从AudioFlinger::openOutput_l这个传统调用流程开始.


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);
    ...
}

findSuitableHwDev_l找到合适的device.这个传统的函数.会有什么新的变化


AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
        audio_module_handle_t module,
        audio_devices_t devices)
{
    
    
    ...
        AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i);
        //奏是这里
        sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
    ...
        if (dev->getSupportedDevices(&supportedDevices) == OK &&
                    (supportedDevices & devices) == devices) {
    
    
             return audioHwDevice;
        }
}

我们要关注的奏是这里


sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
//Android 7.1.2中这行代码是这样的
audio_hw_device_t *dev = audioHwDevice->hwDevice();

dev从

/hardware/libhardware/include/hardware/audio.h

中定义的一个结构体,一个函数指针,变成了一个DeviceHalInterface指针.

这个类来自:


//AudioFlinger.cpp的顶部
#include <media/audiohal/DeviceHalInterface.h>

是的,我找的就是你!(对不起,这时候正在听<He`s a Porate>所以有点激动)

扫描二维码关注公众号,回复: 14748879 查看本文章

回到libaudiohal文件夹中去.

#grep -nir DeviceHalInterface
DeviceHalHidl.h:32:class DeviceHalHidl : public DeviceHalInterface, public ConversionHelperHidl
DeviceHalLocal.h:25:class DeviceHalLocal : public DeviceHalInterface

DeviceHalInterface竟然有两儿子,哦不,是两个子类.

我们分别来看看getSupportedDevices方法


status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {                                                                                                       
    // Obsolete.
    return INVALID_OPERATION;
}

status_t DeviceHalLocal::getSupportedDevices(uint32_t *devices) {
    
    
    if (mDev->get_supported_devices == NULL) return INVALID_OPERATION;
    *devices = mDev->get_supported_devices(mDev);
    return OK;
}

感觉AudioFlinger中调用执行的应该是后者.

仔细看看确定一下

/frameworks/av/services/audioflinger/AudioHwDevice.h


sp<DeviceHalInterface>      mHwDevice;
...
sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
...

mHwDevice是在这里初始化的


//AudioHwDevice.h
AudioHwDevice(audio_module_handle_t handle,
                  const char *moduleName,
                  sp<DeviceHalInterface> hwDevice,
                  Flags flags)
        : mHandle(handle)
        , mModuleName(strdup(moduleName))
        , mHwDevice(hwDevice)
        , mFlags(flags) { }

构造函数的初始化列表中初始化的,那么

grep -nir "new AudioHwDevice"
AudioFlinger.cpp:1788:    mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));


audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{
    
    
    ...
        sp<DeviceHalInterface> dev;
        int rc = mDevicesFactoryHal->openDevice(name, &dev);
    ...
        mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
    ...
}

且看mDevicesFactoryHal的初始化


AudioFlinger::AudioFlinger()
{
    
    
    ...
        mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    ...
}

DevicesFactoryHalHybrid.cpp中,create方法的实现(想不明白为啥放在这里):

// static
sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
   
   
    return new DevicesFactoryHalHybrid();
}

好奇查了下Hybrid的意思,竟然是"混血,混合动力"之类的意思.

DevicesFactoryHalInterface::create()其实是new了一个DevicesFactoryHalHybrid:


DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
        : mLocalFactory(new DevicesFactoryHalLocal()),
          mHidlFactory(
#ifdef USE_LEGACY_LOCAL_AUDIO_HAL
                  nullptr
#else
                  new DevicesFactoryHalHidl()
#endif
                       ) {
    
    
}

现在我们可以改成:

DevicesFactoryHalInterface::create()其实是new了一个DevicesFactoryHalHybrid.该对象是一个拥有一个DevicesFactoryHalLocal对象和DevicesFactoryHalHidl对象的混血.

也就是说mDevicesFactoryHal是一个DevicesFactoryHalHybrid对象.前边调用的openDevice方法即:


status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp<DeviceHalInterface> *device) {
    
    
    if (mHidlFactory != 0 && strcmp(AUDIO_HARDWARE_MODULE_ID_A2DP, name) != 0) {
    
    
        return mHidlFactory->openDevice(name, device);
    }
    return mLocalFactory->openDevice(name, device);
}

好的,到了这里,就

花开两朵,各表一支了

HIDL方式

如果mHidlFactory存在,而且要打开的设备不是AUDIO_HARDWARE_MODULE_ID_A2DP(strcmp返回0表示相等).

蓝牙A2DP不会走HIDL?(这个问题估计得另开话题了)

代码走mHidlFactory->openDevice(name, device);即:


status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
    
    
    Return<void> ret = mDevicesFactory->openDevice(
            hidlDevice,
            [&](Result r, const sp<IDevice>& result) { 
                retval = r;    
                if (retval == Result::OK) {     
                    *device = new DeviceHalHidl(result);
                }
            });
}

mDevicesFactory赋值


DevicesFactoryHalHidl::DevicesFactoryHalHidl() {
    
    
    mDevicesFactory = IDevicesFactory::getService();
    ...
}

IDevicesFactory是一个由IDevicesFactory.hal生成的类(这块不清楚的可以看我之前的博客,分析过很多类似的)

HIDL端(跨进程了),有对应的实现方法:

且看看Android的默认实现示例(直接看openDevice好了):

hardware/interfaces/audio/2.0/default/DevicesFactory.cpp


// Methods from ::android::hardware::audio::V2_0::IDevicesFactory follow.
Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb)  {
    
    
    audio_hw_device_t *halDevice;
    Result retval(Result::INVALID_ARGUMENTS);
    sp<IDevice> result;
    const char* moduleName = deviceToString(device);
    if (moduleName != nullptr) {
    
    
        //画重点
        int halStatus = loadAudioInterface(moduleName, &halDevice);
        if (halStatus == OK) {
    
    
            if (device == IDevicesFactory::Device::PRIMARY) {
    
    
                result = new PrimaryDevice(halDevice);
            } else {
    
    
                result = new ::android::hardware::audio::V2_0::implementation::
                    Device(halDevice);
            }
            retval = Result::OK;
        } else if (halStatus == -EINVAL) {
    
    
            retval = Result::NOT_INITIALIZED;
        }
    }
    _hidl_cb(retval, result);
    return Void();
}

重点loadAudioInterface


// static
int DevicesFactory::loadAudioInterface(const char *if_name, audio_hw_device_t **dev)
{
    
    
    ...
    hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
    ...
    audio_hw_device_open(mod, dev);
    ...
}

先不往下分析.回去分析DevicesFactoryHalHybrid::openDevice调用的另一个分支:

传统方式

如果mHidlFactory不存在,或者要打开的设备是AUDIO_HARDWARE_MODULE_ID_A2DP(strcmp(AUDIO_HARDWARE_MODULE_ID_A2DP, name) = 0)

代码走mLocalFactory->openDevice(name, device);

status_t DevicesFactoryHalLocal::openDevice(const char *name, sp<DeviceHalInterface> *device) {
    
    
    audio_hw_device_t *dev;
    status_t rc = load_audio_interface(name, &dev);
    if (rc == OK) {
    
    
        //重点在这里
        *device = new DeviceHalLocal(dev);
    }
    return rc;
}

static status_t load_audio_interface(const char *if_name, audio_hw_device_t **dev)
{
    
    
     ...
        rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
     ...
        rc = audio_hw_device_open(mod, dev);
     ...        
}

到这里,终于找到了调用getSupportedDevices的dev的真实类型.就是DeviceHalLocal喽!

如果这是一道证明题的,这里可以写一个证毕了!

接下来,我们继续分析


status_t DeviceHalLocal::getSupportedDevices(uint32_t *devices) {
    
    
    if (mDev->get_supported_devices == NULL) return INVALID_OPERATION;
    *devices = mDev->get_supported_devices(mDev);
    return OK;
}

mDev:


DeviceHalLocal::DeviceHalLocal(audio_hw_device_t *dev)
        : mDev(dev) {
    
    
}

即前面一点点提到的audio_hw_device_open(mod, dev)带回来的dev.

以下就是传统方式和HIDL方式都会去调用的audio.h中的接口了.

./hardware/libhardware/include/hardware/audio.h


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));
}

到这里,我们就知道调用的是谁啦.这块有疑问的,可以找找之前很多人分析过的hal层和framework层的调用流程.

没错,它调用的就是audio_hw.c中的adev_open函数.再往下呢,就到了bsp层了.就不继续分析了!

剩下的没涉及到的文件,StreamHalXXX这几个文件,我在另一篇博客中做过分析:

http://blog.csdn.net/bberdong/article/details/78346729

EffectsXXX的音效相关的,感兴趣的读者可以自己研究下,估计大同小异啦!

这篇文章到这里就结束了!谢谢大家观赏!

猜你喜欢

转载自blog.csdn.net/bberdong/article/details/79472208
今日推荐