/*****************************************************************************************************************/
声明: 本博客内容均由https://blog.csdn.net/weixin_47702410原创,转载or引用请注明出处,谢谢!
创作不易,如果文章对你有帮助,麻烦点赞 收藏支持~感谢
/*****************************************************************************************************************/
在上篇文章中我们分析了new AudioPolicyManager(clientInterface, audiopolicymanager_IC_manu_name)的过程,但是却没有分析到AudioPolicyManger的一个初始化过程,本章就以AudioPolicy&AudioFliger To AudioHAL为线索进行分析:
/frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
ALOGE("%s Mylog_AP: new AudioPolicyManager !!! !", __func__);
AudioPolicyManager *apm = new AudioPolicyManager(clientInterface, audiopolicymanager_IC_manu_name);
ALOGE("%s Mylog_AP: new AudioPolicyManager done !", __func__);
status_t status = apm->initialize();
ALOGE("%s Mylog_AP: apm->initialize() !", __func__);
...
}
在上面的函数中,下面的语句就会使Framework C++ Native连接到IC_manu Audio HAL
status_t status = apm->initialize();
在上面的语句中apm其实就是AudioPolicyManager的简称,这个函数最终会调到下面的函数:
/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::initialize() {
{
...
// after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
// open all output streams needed to access attached devices
onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
// make sure default device is reachable
if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable",
mDefaultOutputDevice->toString().c_str());
status = NO_INIT;
}
...
}
其中onNewAudioModulesAvailableInt函数就会建立Framework JAVA Native To Audio HAL的关系,函数原型如下:
xref: /frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
{
...
hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName())); // 加载音频硬件模块
if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
ALOGW("could not open HW module %s", hwModule->getName());
continue;
}
...
}
loadHwModule的定义如下:
xref: /frameworks/av/services/audioflinger/AudioFlinger.cpp
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{
if (name == NULL) {
return AUDIO_MODULE_HANDLE_NONE;
}
if (!settingsAllowed()) {
return AUDIO_MODULE_HANDLE_NONE;
}
Mutex::Autolock _l(mLock);
AutoMutex lock(mHardwareLock);
return loadHwModule_l(name);
}
其中loadHwModule_l的定义如下:
audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
ALOGW("loadHwModule() module %s already loaded", name);
return mAudioHwDevs.keyAt(i);
}
}
sp<DeviceHalInterface> dev;
int rc = mDevicesFactoryHal->openDevice(name, &dev);
...
}
重点关注这个openDevice函数,其会加载HAL并并将其封装在一个DeviceHalInterface对象中。
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;
}
关注一下,这个选择加载HAL的过程,即函数load_audio_interface,它的原型如下:
static status_t load_audio_interface(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 = BAD_VALUE;
audio_hw_device_close(*dev);
goto out;
}
return OK;
out:
*dev = NULL;
return rc;
}
上面的函数中hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod)
就会获取HW Module的名字:
这个AUDIO_HARDWARE_MODULE_ID的定义就是Audio,原型如下:
/hardware/libhardware/include/hardware/
H A D audio.h 38 #define AUDIO_HARDWARE_MODULE_ID "audio"
参数"if_name"的数值在上层中传递下来,具体在函数AudioPolicyManager::onNewAudioModulesAvailableInt中传递,如下代码片段:
hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName())); 加载音频硬件模块
即参数"if_name"是"hwModule"的名字。
hwModule->getName()
这个名字通常具体在配置文件(*xml,例如Audio_policy_configuration.xml)中获取,通常有primary、A2dp、Usb、Remote Submix Audio这四种名字。见下篇文章分析。
继续分析源码:
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int i = 0;
char prop[PATH_MAX] = {0};
char path[PATH_MAX] = {0};
char name[PATH_MAX] = {0};
char prop_name[PATH_MAX] = {0};
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
//合成audio.primary或者audio.$moudle_name
else
strlcpy(name, class_id, PATH_MAX);
/*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/
/* First try a property specific to the class and possibly instance */
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Loop through the configuration variants looking for a module */
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Nothing found, try the default */
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
return -ENOENT;
found:
/* load the module, if this fails, we're doomed, and we should not try
* to load a different variant. */
return load(class_id, path, module);
}
可以看到源码中还会获取property来具体确定调用那个HAL中了,获取的property是ro.hardware(没有则是:ro.product.board、ro.board.platform、ro.arch),查看板子这个property是什么:
static const char *variant_keys[] = {
"ro.hardware", /* This goes first so that it can pick up a different
file on the emulator. */
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
板子的情况:
Android_S:/vendor/lib64/hw # ls audio*
audio.bluetooth.default.so audio.primary.IC_manu_name.so audio.r_submix.default.so audio.r_submix.IC_name_1.so audio_policy.stub.so
audio.primary.default.so audio.primary.IC_name_1.so audio.r_submix.IC_manu_name.so audio.usb.default.so
Android_S:/vendor/lib64/hw #
Android_S:/vendor/lib64/hw # getprop ro.hardware
IC_name_2
Android_S:/vendor/lib64/hw # getprop ro.product.board
Android_S
Android_S:/vendor/lib64/hw # getprop ro.board.platform
IC_name_1
Android_S:/vendor/lib64/hw # getprop ro.arch
Android_S:/vendor/lib64/hw #
可见最终加载的是audio.primary.IC_name_1.so这个so文件,那么这个so文件哪里来的?在下面来的:
\vendor\IC_manu_name\proprietary\hardware\audio
LOCAL_ARM_MODE := arm
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_OWNER := IC_manu_name
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
最终产物是audio.primary.IC_name_1.so
这个就是链接到IC_manu_name HAL那边了,后续可以通过这个so访问到IC_manu_name HAL。