android8.1 的HIDL接口、添加 ALSA 声卡驱动

此篇博文是上一篇文章 《Android 7.1 系统裁剪、定制化实践 snd-aloop 内录音》 的延续. 链接如下:
https://blog.csdn.net/weixin_38387929/article/details/123506727?spm=1001.2014.3001.5502

早期验证 ALSA 声卡内录音的功能,是在 android7.0 系统上,待向 android8.1 系统上移植时,我尴尬了 -
因为硬件驱动 HIDL 的接口在 android8.0 版本的引入,致使我只能在梳理声卡驱动启动过程以及安卓系统调用过程,
因此就有了这篇文章的产生,也分享出来、供有此需求朋友参考。

1. 配置文件入口

android_build 是 imx8mq的安卓源码根

android_build/device/fsl/imx8

|-- AndroidProducts.mk
|-- BoardConfigCommon.mk
|-- arm2_8q.mk
|-- arm2_8q_car.mk
|-- etc
|-- evk_8mq.mk
|-- evk_8mq_drm.mk
|-- imx8.mk                     //>  imx8 通过配置内容,涉及到声卡源码编译配置
|-- imx8_target_fs.mk
|-- init.recovery.freescale.rc
|-- mek_8q.mk                  //> 实验用开发板型号,该开发板声卡配置相关内容.
|-- mek_8q_car.mk
|-- optee-packages.mk
|-- sepolicy
|-- sepolicy_drm
|-- soc
`-- vendorsetup.sh

1.1 BoardConfigCommon.mk 声卡部分如下


BOARD_SOC_CLASS := IMX8

BOARD_KERNEL_OFFSET := 0x00080000
BOARD_RAMDISK_OFFSET := 0x04000000
BOARD_SECOND_OFFSET := 0x03000000

BOARD_MKBOOTIMG_ARGS := --ramdisk_offset $(BOARD_RAMDISK_OFFSET) --second_offset $(BOARD_SECOND_OFFSET) --kernel_offset $(BOARD_KERNEL_OFFSET)

#BOARD_USES_GENERIC_AUDIO := true     //> 注销通用声卡配置
BOARD_USES_ALSA_AUDIO := true         //> 开启 ALSA AUDIO 源码模块编译配置
BOARD_HAVE_BLUETOOTH := true
USE_CAMERA_STUB := false

BOARD_HAVE_IMX_CAMERA := true
BOARD_HAVE_USB_CAMERA := false

1.2 imx8.mk 中声卡部分如下

#audio related lib
PRODUCT_PACKAGES += \
        audio.primary.imx8                      \
        tinyplay                                \
        audio.a2dp.default                      \
        audio.usb.default                       \
        audio.r_submix.default                  \
        tinycap                                 \
        tinymix                                 \
        libsrec_jni                             \
        libtinyalsa                             \
        libaudioutils

1.3 mek_8q.mk 声卡相关配置

# Audio
USE_XML_AUDIO_POLICY_CONF := 1
PRODUCT_COPY_FILES += \
        device/fsl/mek_8q/audio_effects.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.conf \
        device/fsl/mek_8q/audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_configuration.xml \
        frameworks/av/services/audiopolicy/config/a2dp_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/a2dp_audio_policy_configuration.xml \
        frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/r_submix_audio_policy_configuration.xml \
        frameworks/av/services/audiopolicy/config/usb_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/usb_audio_policy_configuration.xml \
        frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
        frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_volumes.xml \


PRODUCT_PACKAGES += \
    android.hardware.audio@2.0-impl \
    android.hardware.audio@2.0-service \
    android.hardware.audio.effect@2.0-impl \
    android.hardware.sensors@1.0-impl \
    android.hardware.sensors@1.0-service \
    android.hardware.power@1.0-impl \
    android.hardware.power@1.0-service \
    android.hardware.light@2.0-impl \
    android.hardware.light@2.0-service

2. android8.1 的声卡 audio_policy_configuration.xml 与 android7 的差异

android8.1 与 adroid7 的 audio_policy_configuration.xml 配置文件,属于兼容。

3. 声卡驱动源码移植

3.1). 声卡驱动的创建过程

android8.0 系统驱动采用 HIDL 方式,驱动作为独立服务在系统中存在,安卓系统调用驱动是采用 STUB 服务绑定
方式, 获取驱动的代理句柄、来使用驱动相关的api接口功能。

声卡 hidl 实现相关代码路径及内容如下

robot@ubuntu:~/aosp8.1/hardware/interfaces/audio/2.0/default$ tree -L 1
.
|-- Android.mk
|-- Conversions.cpp
|-- Conversions.h
|-- Device.cpp
|-- Device.h
|-- DevicesFactory.cpp
|-- DevicesFactory.h
|-- OWNERS
|-- ParametersUtil.cpp
|-- ParametersUtil.h
|-- PrimaryDevice.cpp
|-- PrimaryDevice.h
|-- Stream.cpp
|-- Stream.h
|-- StreamIn.cpp
|-- StreamIn.h
|-- StreamOut.cpp
|-- StreamOut.h
|-- Util.h
|-- android.hardware.audio@2.0-service.rc //> 声卡驱动服务的系统启动配置文件
`-- service.cpp                           //> audio 驱动服务启动和注册源码

首先看 Android.mk 内容如下:

include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.audio@2.0-impl
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_SRC_FILES := \
    Conversions.cpp \
    Device.cpp \
    DevicesFactory.cpp \
    ParametersUtil.cpp \
    PrimaryDevice.cpp \
    Stream.cpp \
    StreamIn.cpp \
    StreamOut.cpp \

#
# Service
#

include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.audio@2.0-service
LOCAL_INIT_RC := android.hardware.audio@2.0-service.rc
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_SRC_FILES := \
    service.cpp

LOCAL_SHARED_LIBRARIES := \
    libhidlbase \
    libhidltransport \
    liblog \
    libutils \
    libhardware \
    android.hardware.audio@2.0 \
    android.hardware.audio.common@2.0 \
    android.hardware.audio.effect@2.0 \
    android.hardware.soundtrigger@2.0 \
    android.hardware.broadcastradio@1.0 \
    android.hardware.broadcastradio@1.1

ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
LOCAL_MULTILIB := 32
else
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
endif

此部分是声卡服务程序 service.cpp 的编译文件,此部分是实现 AUDIO_HARDWARE_MODULE_ID_STUB 模式,
即声卡 HIDL 绑定模式代码,如果采用直通模式、兼容以前版本声卡模式,是如何实现的呢?
我们先看一下 DevicesFactory.cpp 和 DevicesFactory.h 源码,内容如下:

@ aosp8.1/hardware/interfaces/audio/2.0/default/DevicesFactory.h

#ifndef ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
#define ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H

#include <hardware/audio.h>

#include <android/hardware/audio/2.0/IDevicesFactory.h>
#include <hidl/Status.h>

#include <hidl/MQDescriptor.h>
namespace android {
    
    
namespace hardware {
    
    
namespace audio {
    
    
namespace V2_0 {
    
    
namespace implementation {
    
    

using ::android::hardware::audio::V2_0::IDevice;
using ::android::hardware::audio::V2_0::IDevicesFactory;
using ::android::hardware::audio::V2_0::Result;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;

struct DevicesFactory : public IDevicesFactory {
    
    
    // Methods from ::android::hardware::audio::V2_0::IDevicesFactory follow.
    Return<void> openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb)  override;

  private:
    static const char* deviceToString(IDevicesFactory::Device device);
    static int loadAudioInterface(const char *if_name, audio_hw_device_t **dev);

};

extern "C" IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name);

}  // namespace implementation
}  // namespace V2_0
}  // namespace audio
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H

文件中开启 audio 的 passthrough 模式,
extern “C” IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name);
此函数导出到 C 语音空间,可以通过c语音调用此函数;

函数实现如下:
@ aosp8.1/hardware/interfaces/audio/2.0/default/DevicesFactory.cpp


#define LOG_TAG "DevicesFactoryHAL"

#include <string.h>

#include <android/log.h>

#include "Device.h"
#include "DevicesFactory.h"
#include "PrimaryDevice.h"

namespace android {
    
    
namespace hardware {
    
    
namespace audio {
    
    
namespace V2_0 {
    
    
namespace implementation {
    
    

// static
const char* DevicesFactory::deviceToString(IDevicesFactory::Device device) {
    
    
    switch (device) {
    
    
        case IDevicesFactory::Device::PRIMARY: return AUDIO_HARDWARE_MODULE_ID_PRIMARY;
        case IDevicesFactory::Device::A2DP: return AUDIO_HARDWARE_MODULE_ID_A2DP;
        case IDevicesFactory::Device::USB: return AUDIO_HARDWARE_MODULE_ID_USB;
        case IDevicesFactory::Device::R_SUBMIX: return AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX;
        case IDevicesFactory::Device::STUB: return AUDIO_HARDWARE_MODULE_ID_STUB;
    }
    return nullptr;
}

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

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

IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) {
    
    
    return new DevicesFactory();
}

}  // namespace implementation
}  // namespace V2_0
}  // namespace audio
}  // namespace hardware
}  // namespace android

函数 HIDL_FETCH_IDevicesFactory() 只是简单创建声卡设备对象,也由此开启声卡驱动加载和应用过程。
由头文件看到,对象构建时调用的函数是 openDevice() 函数,兼容早期版本声卡驱动是通过 deviceToString()
函数,把设备转化成对应驱动名称,然后通过名称获取不同声卡驱动实例、来使用驱动.
如:AUDIO_HARDWARE_MODULE_ID_PRIMARY、AUDIO_HARDWARE_MODULE_ID_A2DP、AUDIO_HARDWARE_MODULE_ID_USB
、AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX 和 AUDIO_HARDWARE_MODULE_ID_STUB,早期版本是PRIMARY、A2DP、
USB、REMOTE_SUBMIX 几类声卡模式. STUB 是 android8.0 扩展模式,通过此方法实现两个版本驱动兼容。

3.2). 声卡驱动匹配过程

前面博文中有描述安卓系统声卡 audioFlinger 相关文章,参考链接.
https://blog.csdn.net/weixin_38387929/article/details/123136466

简单回顾一下:
安卓系统在启动时将启动 audioService 服务,该服务会创建

        AudioFlinger::instantiate();         //> @frameworks/av/services/audioflinger/audioFlinger.hpp
        AudioPolicyService::instantiate();   //> @frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
        RadioService::instantiate();
        SoundTriggerHwService::instantiate();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();

audioFlinger、AudioPolicyService、SoundTriggerHwService和IPCThreadState线程池线程,由此处开始引入 audioFlinger 启动.

接下来我们走读一下这块代码。
@aosp8.1/frameworks/av/services/audioflinger/AudioFlinger.cpp 和 .h 文件,调用如下接口

AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
      mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
      mPrimaryHardwareDev(NULL),
      mAudioHwDevs(NULL),
      mHardwareStatus(AUDIO_HW_IDLE),
      mMasterVolume(1.0f),
      mMasterMute(false),
      // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
      mMode(AUDIO_MODE_INVALID),
      mBtNrecIsOff(false),
      mIsLowRamDevice(true),
      mIsDeviceTypeKnown(false),
      mGlobalEffectEnableTime(0),
      mSystemReady(false)
    {
    
    
        const bool doLog = property_get_bool("ro.test_harness", false);
        if (doLog) {
    
    
            mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
                        MemoryHeapBase::READ_ONLY);
            (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
        }

        // reset battery stats.
        // if the audio service has crashed, battery stats could be left
        // in bad state, reset the state upon service start.
        BatteryNotifier::getInstance().noteResetAudio();
        mDevicesFactoryHal = DevicesFactoryHalInterface::create();      //> 调用设备工厂的创建方法
        mEffectsFactoryHal = EffectsFactoryHalInterface::create();

        mMediaLogNotifier->run("MediaLogNotifier");
    }

3.2.1). stub hal 模式

此接口内容如下:
@ aosp8.1/frameworks/av/media/libaudiohal/DevicesFactoryHalHidl.cpp 和 .h 文件.

#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H
#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H

#include <android/hardware/audio/2.0/IDevicesFactory.h>
#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>

#include "DeviceHalHidl.h"

using ::android::hardware::audio::V2_0::IDevicesFactory;

namespace android {
    
    

class DevicesFactoryHalHidl : public DevicesFactoryHalInterface    //> 继承 DevicesFactoryHalInterface 类
{
    
    
  public:
    // Opens a device with the specified name. To close the device, it is
    // necessary to release references to the returned object.
    virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);

  private:
    friend class DevicesFactoryHalHybrid;

    sp<IDevicesFactory> mDevicesFactory;

    static status_t nameFromHal(const char *name, IDevicesFactory::Device *device);

    // Can not be constructed directly by clients.
    DevicesFactoryHalHidl();

    virtual ~DevicesFactoryHalHidl();
};

} // namespace android

#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H

STUB HAL模式 DevicesFactoryHalHidl 继承 DevicesFactoryHalInterface 类,由此我们基本可以推断应该还有一个
早期版本 HAL 类也继承 DevicesFactoryHalInterface 类,以此方法实现兼容两个版本驱动的目的。

DevicesFactoryHalHidl构建方法如下:

DevicesFactoryHalHidl::DevicesFactoryHalHidl() {
    
    
    mDevicesFactory = IDevicesFactory::getService();         //> 通过 STUB HIDL interface 获取 HAL 服务
    if (mDevicesFactory != 0) {
    
    
        // It is assumed that DevicesFactory is owned by AudioFlinger
        // and thus have the same lifespan.
        mDevicesFactory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
    } else {
    
    
        ALOGE("Failed to obtain IDevicesFactory service, terminating process.");
        exit(1);
    }
}

3.2.2). lagecy hal 模式 ( PASSTHROUGH模式)

@aosp8.1/frameworks/av/media/libaudiohal/DevicesFactoryHalLocal.h

#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_LOCAL_H
#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_LOCAL_H

#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>

#include "DeviceHalLocal.h"

namespace android {
    
    

class DevicesFactoryHalLocal : public DevicesFactoryHalInterface
{
    
    
  public:
    // Opens a device with the specified name. To close the device, it is
    // necessary to release references to the returned object.
    virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);

  private:
    friend class DevicesFactoryHalHybrid;

    // Can not be constructed directly by clients.
    DevicesFactoryHalLocal() {
    
    }

    virtual ~DevicesFactoryHalLocal() {
    
    }
};

} // namespace android

#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_LOCAL_H

@aosp8.1/frameworks/av/media/libaudiohal/DevicesFactoryHalHybrid.h

#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HYBRID_H
#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HYBRID_H

#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>

namespace android {
    
    

class DevicesFactoryHalHybrid : public DevicesFactoryHalInterface
{
    
    
  public:
    // Opens a device with the specified name. To close the device, it is
    // necessary to release references to the returned object.
    virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);

  private:
    friend class DevicesFactoryHalInterface;

    // Can not be constructed directly by clients.
    DevicesFactoryHalHybrid();

    virtual ~DevicesFactoryHalHybrid();

    sp<DevicesFactoryHalInterface> mLocalFactory;
    sp<DevicesFactoryHalInterface> mHidlFactory;
};

} // namespace android

#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HYBRID_H

@aosp8.1/frameworks/av/media/libaudiohal/DevicesFactoryHalHybrid.cpp

#define LOG_TAG "DevicesFactoryHalHybrid"
//#define LOG_NDEBUG 0

#include "DevicesFactoryHalHybrid.h"
#include "DevicesFactoryHalLocal.h"
#ifndef USE_LEGACY_LOCAL_AUDIO_HAL
#include "DevicesFactoryHalHidl.h"
#endif

namespace android {
    
    

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

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

DevicesFactoryHalHybrid::~DevicesFactoryHalHybrid() {
    
    
}

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

} // namespace android

至此,我们做简短总结,由上面几段源码可以看出,安卓声卡驱动版本兼容、是通过 DevicesFactoryHalInterface 类的智能指针,
指向不同声卡驱动实例实现。此处代码逻辑关系笔者未详细梳理、谨通过基本特征进行类推。

3.3). DevicesFactoryHalInterface 类

@aosp8.1/frameworks/av/media/libaudiohal/include/media/audiohal/DevicesFactoryHalHidlInterface.h

namespace android {
    
    

class DevicesFactoryHalInterface : public RefBase
{
    
    
  public:
    // Opens a device with the specified name. To close the device, it is
    // necessary to release references to the returned object.
    virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device) = 0;

    static sp<DevicesFactoryHalInterface> create();

  protected:
    // Subclasses can not be constructed directly by clients.
    DevicesFactoryHalInterface() {
    
    }

    virtual ~DevicesFactoryHalInterface() {
    
    }
};

} // namespace android

此类再次继承基类 RefBase 类.
@aosp8.1/system/core/libutils/include/utils/RefBase.h

class RefBase
{
    
    
public:
            void            incStrong(const void* id) const;
            void            decStrong(const void* id) const;
    
            void            forceIncStrong(const void* id) const;

            //! DEBUGGING ONLY: Get current strong ref count.
            int32_t         getStrongCount() const;

    class weakref_type
    {
    
    
    public:
        RefBase*            refBase() const;

        void                incWeak(const void* id);
        void                decWeak(const void* id);

        // acquires a strong reference if there is already one.
        bool                attemptIncStrong(const void* id);

        // acquires a weak reference if there is already one.
        // This is not always safe. see ProcessState.cpp and BpBinder.cpp
        // for proper use.
        bool                attemptIncWeak(const void* id);

        //! DEBUGGING ONLY: Get current weak ref count.
        int32_t             getWeakCount() const;

        //! DEBUGGING ONLY: Print references held on object.
        void                printRefs() const;

        //! DEBUGGING ONLY: Enable tracking for this object.
        // enable -- enable/disable tracking
        // retain -- when tracking is enable, if true, then we save a stack trace
        //           for each reference and dereference; when retain == false, we
        //           match up references and dereferences and keep only the
        //           outstanding ones.

        void                trackMe(bool enable, bool retain);
    };

            weakref_type*   createWeak(const void* id) const;
            
            weakref_type*   getWeakRefs() const;

            //! DEBUGGING ONLY: Print references held on object.
    inline  void            printRefs() const {
    
     getWeakRefs()->printRefs(); }

            //! DEBUGGING ONLY: Enable tracking of object.
    inline  void            trackMe(bool enable, bool retain)
    {
    
     
        getWeakRefs()->trackMe(enable, retain); 
    }

    typedef RefBase basetype;

protected:
                            RefBase();
    virtual                 ~RefBase();
    
    //! Flags for extendObjectLifetime()
    enum {
    
    
        OBJECT_LIFETIME_STRONG  = 0x0000,
        OBJECT_LIFETIME_WEAK    = 0x0001,
        OBJECT_LIFETIME_MASK    = 0x0001
    };
    
    void   extendObjectLifetime(int32_t mode);
            
    //! Flags for onIncStrongAttempted()
    enum {
    
    
        FIRST_INC_STRONG = 0x0001
    };
    
    // Invoked after creation of initial strong pointer/reference.
    virtual void            onFirstRef();
    // Invoked when either the last strong reference goes away, or we need to undo
    // the effect of an unnecessary onIncStrongAttempted.
    virtual void            onLastStrongRef(const void* id);
    // Only called in OBJECT_LIFETIME_WEAK case.  Returns true if OK to promote to
    // strong reference. May have side effects if it returns true.
    // The first flags argument is always FIRST_INC_STRONG.
    // TODO: Remove initial flag argument.
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    // Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
    // kind goes away.  Unused.
    // TODO: Remove.
    virtual void            onLastWeakRef(const void* id);

private:
    friend class weakref_type;
    class weakref_impl;
    
                            RefBase(const RefBase& o);
            RefBase&        operator=(const RefBase& o);

private:
    friend class ReferenceMover;

    static void renameRefs(size_t n, const ReferenceRenamer& renamer);

    static void renameRefId(weakref_type* ref,
            const void* old_id, const void* new_id);

    static void renameRefId(RefBase* ref,
            const void* old_id, const void* new_id);

        weakref_impl* const mRefs;
};

@aosp8.1/system/core/libutils/RefBase.cpp:

RefBase::RefBase()
    : mRefs(new weakref_impl(this))
{
    
    
}

class RefBase::weakref_impl : public RefBase::weakref_type
{
    
    
public:
    std::atomic<int32_t>    mStrong;
    std::atomic<int32_t>    mWeak;
    RefBase* const          mBase;
    std::atomic<int32_t>    mFlags;


    weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)
        , mFlags(0)
        , mStrongRefs(NULL)
        , mWeakRefs(NULL)
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
        , mRetain(false)
    {
    
    
    }
    mutable Mutex mMutex;
    ref_entry* mStrongRefs;
    ref_entry* mWeakRefs;

    bool mTrackEnabled;
    // Collect stack traces on addref and removeref, instead of deleting the stack references
    // on removeref that match the address ones.
    bool mRetain;

};

至此、我们把 audioflinger 启动和驱动匹配过程源码粗略走读一遍。

3.4). 移植 ALSA 声卡

在 @ aosp8.1/hardware/libhardware/modules/ 路径中,有各种声卡模块驱动代码.
我们修改的是 audio.primary.${TARGET_BOARD_HARDWARE} 声卡驱动,在 AudioPolicyService 选择驱动中是首选与
TARGET_BOARD_HARDWARE 目标板匹配的声卡驱动,如果没有才会匹配 audio.primary.default 驱动。

3.5). 录音验证

把 android8.1 的alsa驱动移植后,编译内核烧入mek8q开发板中,通过实际录音验证,文章对HIDL接口驱动兼容方法,分析
基本是正确的。

android8.1 的驱动移植参考 hidl 参考
https://justinwei.blog.csdn.net/article/details/86530600

猜你喜欢

转载自blog.csdn.net/weixin_38387929/article/details/124754681
今日推荐