此篇博文是上一篇文章 《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