AudioHAL
先看看和Audio有关的hal文件 具体路径/hardware/interfaces/audio/文件夹下(这里看的是6.0的)
大致结构图
- IDeviceFactory.hal:打开设备,并返回此设备
- IDevice.hal:设备相关的配置,信息,操作等
- IStream.hal:输入输出流相关的信息
- Callback.hal:返回流相关的状态信息
- types.hal:图上没画,因为还不知道是干什么用的
![](https://img.haomeiwen.com/i27607674/278f6181856c426a.png)
AudioFlinger和HAL
在分析AudioFlinger的时候留下的和HAL有关的三个地方
- AudioFlinger构造函数:DevicesFactoryHalInterface::create();
- loadHwModule_l打开设备:mDevicesFactoryHal->openDevice(name, &dev)
- openOutput_l打开流:outHwDev->openOutputStream(...)
DevicesFactoryHalInterface::create()
- 执行流程:DevicesFactoryHalInterface --> FactoryHalHidl --> DevicesFactoryHalHybrid --> DevicesFactoryHalHidl
- 结果:返回mDevicesFactoryHal = DevicesFactoryHalHybrid对象,他可以调用IDeviceFactory.hal 里面的方法了
![](https://img.haomeiwen.com/i27607674/bd746c15ed45455a.png)
DevicesFactoryHalInterface.cpp
# av/media/libaudiohal/DevicesFactoryHalInterface.cpp
// lyh createPreferredImpl方法在FactoryHalHidl.cpp中
sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
return createPreferredImpl<DevicesFactoryHalInterface>(
"android.hardware.audio", "IDevicesFactory");
}
FactoryHalHidl.cpp
# av/media/libaudiohal/FactoryHalHidl.cpp
const char* sAudioHALVersions[] = {"6.0", "5.0", "4.0", "2.0",nullptr};
// lyh 这里传入的两个参数
// lyh package --> android.hardware.audio
// lyh interface --> IDevicesFactory
void* createPreferredImpl(const std::string& package, const std::string& interface) {
for (auto version = detail::sAudioHALVersions; version != nullptr; ++version) {
void* rawInterface = nullptr;
if (hasHalService(package, *version, interface)
&& createHalService(*version, interface, &rawInterface)) {
return rawInterface;
}
}
return nullptr;
}
// lyh 真正创建的地方
bool createHalService(const std::string& version, const std::string& interface,
void** rawInterface) {
// lyh 动态库的名称:libaudiohal@x.0.so
// lyh libaudiohal封装了audio HIDL的接口,以libaudiohal.so的形式供AudioFlinger使用
const std::string libName = "libaudiohal@" + version + ".so";
// lyh 猜测是动态库里面的函数名称:createIDevicesFactory
const std::string factoryFunctionName = "create" + interface;
constexpr int dlMode = RTLD_LAZY;
void* handle = nullptr;
dlerror(); // clear
// lyh dlopen 加载动态库
handle = dlopen(libName.c_str(), dlMode);
if (handle == nullptr) {
const char* error = dlerror();
ALOGE("Failed to dlopen %s: %s", libName.c_str(),
error != nullptr ? error : "unknown error");
return false;
}
// lyh 用函数指针接受这个create方法
void* (*factoryFunction)();
// lyh dlsym 查找方法,返回地址
*(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
if (!factoryFunction) {
const char* error = dlerror();
ALOGE("Factory function %s not found in library %s: %s",
factoryFunctionName.c_str(), libName.c_str(),
error != nullptr ? error : "unknown error");
dlclose(handle);
return false;
}
// lyh 调用
*rawInterface = (*factoryFunction)();
ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
factoryFunctionName.c_str(), libName.c_str());
return true;
}
// lyh 就是查一下有没有这个本版的HalService
bool hasHalService(const std::string& package, const std::string& version,
const std::string& interface) {
using ::android::hidl::manager::V1_0::IServiceManager;
// lyh ServiceManager
sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
if (!sm) {
ALOGE("Failed to obtain HIDL ServiceManager");
return false;
}
// Since audio HAL doesn't support multiple clients, avoid instantiating
// the interface right away. Instead, query the transport type for it.
using ::android::hardware::Return;
using Transport = IServiceManager::Transport;
// lyh fqName = "android.hardware.audio@x.0::IDevicesFactory"
const std::string fqName = package + "@" + version + "::" + interface;
const std::string instance = "default";
Return<Transport> transport = sm->getTransport(fqName, instance);
if (!transport.isOk()) {
ALOGE("Failed to obtain transport type for %s/%s: %s",
fqName.c_str(), instance.c_str(), transport.description().c_str());
return false;
}
return transport != Transport::EMPTY;
}
} // namespace
DevicesFactoryHalHybrid.cpp
# av/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
被调用的方法就在这里
DevicesFactoryHalHybrid::DevicesFactoryHalHybrid(sp<IDevicesFactory> hidlFactory)
: mLocalFactory(new DevicesFactoryHalLocal()),
// 构造函数新建了DevicesFactoryHalHidl对象并赋值,且把service传入
mHidlFactory(new DevicesFactoryHalHidl(hidlFactory)) {
}
// lyh FactoryHalHidl加载动态库后调用的方法
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
// lyh 因为service有值,所以走构造函数,把service传入
return service ? new CPP_VERSION::DevicesFactoryHalHybrid(service) : nullptr;
}
DevicesFactoryHalHidl.cpp
# av/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
DevicesFactoryHalHidl::DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory) {
ALOG_ASSERT(devicesFactory != nullptr, "Provided default IDevicesFactory service is NULL");
// 这个时候就已经把devicesFactory = IDeviceFactory::getService保存起来了,就已经可以和HAL通信了
addDeviceFactory(devicesFactory, false /*needToNotify*/);
}
// lyh 熟悉的onFirstRef
void DevicesFactoryHalHidl::onFirstRef() {
// lyh 拿到ServiceManager
sp<IServiceManager> sm = IServiceManager::getService();
// lyh 创建注册监听
sp<ServiceNotificationListener> listener = new ServiceNotificationListener(this);
// lyh 不是很懂这句话真正的意思,
Return<bool> result = sm->registerForNotifications(
IDevicesFactory::descriptor, "", listener);
}
// lyh 不知道基于什么去发送通知,根据方法名像是注册Service时发送的
class ServiceNotificationListener : public IServiceNotification {
public:
explicit ServiceNotificationListener(sp<DevicesFactoryHalHidl> factory)
: mFactory(factory) {}
//
Return<void> onRegistration(const hidl_string& /*fully_qualified_name*/,
const hidl_string& instance_name,
bool /*pre_existing*/) override {
if (static_cast<std::string>(instance_name) == "default") return Void();
sp<DevicesFactoryHalHidl> factory = mFactory.promote();
if (!factory) return Void();
// lyh HIDL 获取IDeviceFractory.hal
// lyh /hardware/interfaces/audio/core/
sp<IDevicesFactory> halFactory = IDevicesFactory::getService(instance_name);
if (halFactory) {
factory->addDeviceFactory(halFactory, true /*needToNotify*/);
}
return Void();
}
private:
wp<DevicesFactoryHalHidl> mFactory;
};
DevicesFactoryHalHidl
loadHwModule_l打开设备
经过上面的步骤已经可以调用到IDeviceFactory的方法了,所以执行方法也就是走流程的事情
- 执行流程:AuioFlinger -> DevicesFactoryHalHidl -> DevicesFactoryHalHybrid -> DeviceFactory -> audio.c(打开设备)
- 得到的结果:audio_hw_device_open打开设备,经过包装成IDevice对象返回,然后接着包装返回
![](https://img.haomeiwen.com/i27607674/6aa4f3d4bb6ada1b.png)
![](https://img.haomeiwen.com/i27607674/46d57c67fe184066.png)
DevicesFactoryHalHybrid.cpp
# av/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
// lyh AudioFlinger调用的方法就是这个
status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp<DeviceHalInterface> *device) {
// lyh 根据name值决定使用hidl类还是local类, 区别??
if (mHidlFactory != 0 && strcmp(AUDIO_HARDWARE_MODULE_ID_A2DP, name) != 0 &&
strcmp(AUDIO_HARDWARE_MODULE_ID_HEARING_AID, name) != 0) {
// lyh 这里进入DevicesFactoryHalHidl.cpp
return mHidlFactory->openDevice(name, device);
}
// lyh 这个还不知道是什么时候调用的
return mLocalFactory->openDevice(name, device);
}
DevicesFactoryHalHidl.cpp
# av/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
auto factories = copyDeviceFactories();
// lyh 获取Device类型
auto hidlId = idFromHal(name, &status);
Result retval = Result::NOT_INITIALIZED;
for (const auto& factory : factories) {
// lyh 跨进程调用 --> DevicesFactory,根据类型创建Device
Return<void> ret = factory->openDevice(
hidlId,
[&](Result r, const sp<IDevice>& result) {
retval = r;
if (retval == Result::OK) {
// 回调出来的执行 传入IDevice对象,进行一层包装
*device = new DeviceHalHidl(result);
}
});
}
return BAD_VALUE;
}
DeviceFacotry.cpp
# hardware/interfaces/audio/core/all-versions/default/DeviceFacotry.cpp
// lyh 这里省略了前面的代码,直接看最后执行的方法,这里的模板类DeviceShim就是Device.cpp
template <class DeviceShim, class Callback>
Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
audio_hw_device_t* halDevice;
Result retval(Result::INVALID_ARGUMENTS);
sp<DeviceShim> result;
// lyh
int halStatus = loadAudioInterface(moduleName, &halDevice);
if (halStatus == OK) {
// lyh DeviceShim 泛形
result = new DeviceShim(halDevice);
retval = Result::OK;
} else if (halStatus == -EINVAL) {
retval = Result::NOT_INITIALIZED;
}
// lyh 回调Callback
_hidl_cb(retval, result);
return Void();
}
int DevicesFactory::loadAudioInterface(const char* if_name, audio_hw_device_t** dev) {
const hw_module_t* mod;
int rc;
// lyh hw_get_module_by_class动态链接 hal 库,
// 如:audio.primary.default.so、audio.a2dp.default.so、audio.usb.default.so
rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
// lyh open device
rc = audio_hw_device_open(mod, dev);
return OK;
}
openOutput_l打开流
调用流程:AudioFlinger -> AudioHwDevice -> AudioStreamOut -> DeviceHalHidl -> Device.cpp -> audio.h 得到结果:拿到输出流后,包装成IStreamOut,在向上一层层包装
AudioFlinger.cpp
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l()
{
// lyh 找到合适输出设备
AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);
// lyh 输出流
AudioStreamOut *outputStream = NULL;
// lyh 打开输出流
status_t status = outHwDev->openOutputStream(
&outputStream,
*output,
deviceType,
flags,
config,
address.string());
if (status == NO_ERROR) {
...
} else {
// lyh 创建播放线程
sp<PlaybackThread> thread;
.... 省略
return thread;
}
}
return 0;
}
AudioHwDevice.cpp
status_t AudioHwDevice::openOutputStream(
AudioStreamOut **ppStreamOut,
audio_io_handle_t handle,
audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address)
{
struct audio_config originalConfig = *config;
// lyh 把自己AudioHwDevice传入
AudioStreamOut *outputStream = new AudioStreamOut(this, flags);
// lyh 打开流
status_t status = outputStream->open(handle, deviceType, config, address);
*ppStreamOut = outputStream;
return status;
}
AudioStreamOut.cpp
status_t AudioStreamOut::open(
audio_io_handle_t handle,
audio_devices_t deviceType,
struct audio_config *config,
const char *address)
{
sp<StreamOutHalInterface> outStream;
// lyh 调用DeviceHalHidl的方法,hwDev就是获取DeviceHalHidl对象
int status = hwDev()->openOutputStream(
handle,
deviceType,
customFlags,
config,
address,
&outStream);
}
if (status == NO_ERROR) {
stream = outStream;
mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
status = stream->getFrameSize(&mHalFrameSize);
}
return status;
}
DeviceHalHidl.cpp
status_t DeviceHalHidl::openOutputStream(
audio_io_handle_t handle,
audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address,
sp<StreamOutHalInterface> *outStream) {
if (mDevice == 0) return NO_INIT;
DeviceAddress hidlDevice;
status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
if (status != OK) return status;
AudioConfig hidlConfig;
HidlUtils::audioConfigFromHal(*config, &hidlConfig);
Result retval = Result::NOT_INITIALIZED;
// lyh IDevice
Return<void> ret = mDevice->openOutputStream(.hal
handle,
hidlDevice,
hidlConfig,
EnumBitfield<AudioOutputFlag>(flags),
#if MAJOR_VERSION >= 4
{} /* metadata */,
#endif
[&](Result r, const sp<IStreamOut>& result, const AudioConfig& suggestedConfig) {
retval = r;
if (retval == Result::OK) {
*outStream = new StreamOutHalHidl(result);
}
HidlUtils::audioConfigToHal(suggestedConfig, config);
});
return processReturn("openOutputStream", ret, retval);
}
网友评论