Analyse du module Android O Audio libaudiohal

Pour le module Android O Audio, il existe un dossier libaudiohal supplémentaire :

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

Évidemment, c'est pour hidl.

Étudions comment l'utiliser.

Lors de la lecture audio, vous devez d'abord openOutput Nous commençons par le processus d'appel traditionnel de 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 trouve un appareil adapté. Cette fonction traditionnelle. Quels nouveaux changements y aura-t-il ?


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

Ce sur quoi nous voulons nous concentrer est ici


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

développeur de

/matériel/libhardware/include/matériel/audio.h _ _ _ _ _ _ _ _ _

Une structure définie dans , un pointeur de fonction, devient un pointeur DeviceHalInterface.

Cette classe vient de :


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

Oui, je te cherche ! (Désolé, j'écoute <He`sa Porate> en ce moment , donc je suis un peu excité)

Retournez dans le dossier libaudiohal.

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

DeviceHalInterface a en fait deux fils, oh non, ce sont deux sous-classes.

Jetons un coup d'œil à la méthode getSupportedDevices séparément


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

Il semble que ce dernier devrait être appelé dans AudioFlinger.

regarde de plus près pour t'assurer

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


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

mHwDevice est initialisé ici


//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) { }

initialisé dans la liste des initialiseurs du constructeur, puis

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

Tout de suite


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

Et regardez l'initialisation de mDevicesFactoryHal


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

Dans DevicesFactoryHalHybrid.cpp, l'implémentation de la méthode create (je ne comprends pas pourquoi elle est ici) :

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

Curieusement, j'ai vérifié le sens d'Hybride, il s'est avéré qu'il signifiait "sang mêlé, puissance hybride".

DevicesFactoryHalInterface::create() est en fait un nouveau DevicesFactoryHalHybrid :


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

Maintenant, nous pouvons passer à :

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的音效相关的,感兴趣的读者可以自己研究下,估计大同小异啦!

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

Je suppose que tu aimes

Origine blog.csdn.net/bberdong/article/details/79472208
conseillé
Classement