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
Obviously, it is for hidl.
Let's study how to use it.
When playing Audio, you need to openOutput first. We start with the traditional call process of 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 finds a suitable device. This traditional function. What new changes will there be?
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;
}
}
What we want to focus on is here
sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
//Android 7.1.2中这行代码是这样的
audio_hw_device_t *dev = audioHwDevice->hwDevice();
dev from
A structure defined in , a function pointer, becomes a DeviceHalInterface pointer.
This class comes from:
//AudioFlinger.cpp的顶部
Yes, I am looking for you! (Sorry, I am listening to <He`sa Porate> at this time , so I am a little excited)
Go back to the libaudiohal folder.
#grep -nir DeviceHalInterface DeviceHalHidl.h:32:class DeviceHalHidl : public DeviceHalInterface, public ConversionHelperHidl DeviceHalLocal.h:25:class DeviceHalLocal : public DeviceHalInterface
DeviceHalInterface actually has two sons, oh no, they are two subclasses.
Let's take a look at the getSupportedDevices method separately
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;
}
It feels like the latter should be called in AudioFlinger.
take a closer look to make sure
/frameworks/av/services/audioflinger/AudioHwDevice.h
sp<DeviceHalInterface> mHwDevice;
...
sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
...
mHwDevice is initialized here
//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) { }
initialized in the initializer list of the constructor, then
grep -nir "new AudioHwDevice" AudioFlinger.cpp:1788: mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
Right now
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));
...
}
And look at the initialization of mDevicesFactoryHal
AudioFlinger::AudioFlinger()
{
...
mDevicesFactoryHal = DevicesFactoryHalInterface::create();
...
}
In DevicesFactoryHalHybrid.cpp, the implementation of the create method (I don’t understand why it’s here):
// static sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() { return new DevicesFactoryHalHybrid(); }
Curiously checked the meaning of Hybrid, it turned out to mean "mixed blood, hybrid power".
DevicesFactoryHalInterface::create() is actually a new DevicesFactoryHalHybrid:
DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
: mLocalFactory(new DevicesFactoryHalLocal()),
mHidlFactory(
nullptr
new DevicesFactoryHalHidl()
) {
}
Now we can change to:
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这几个文件,我在另一篇博客中做过分析:
EffectsXXX的音效相关的,感兴趣的读者可以自己研究下,估计大同小异啦!
这篇文章到这里就结束了!谢谢大家观赏!