/*****************************************************************************************************************/
声明: 本博客内容均由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 devicesonNewAudioModulesAvailableInt(nullptr /*newDevices*/);// make sure default device is reachableif (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.cppvoid 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_nameelsestrlcpy(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 differentfile 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.archAndroid_S:/vendor/lib64/hw #
可见最终加载的是audio.primary.IC_name_1.so这个so文件,那么这个so文件哪里来的?在下面来的:
\vendor\IC_manu_name\proprietary\hardware\audioLOCAL_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。