以加载audio.primary.msm8909.so为例: 高通平台,audio primary库文件是有两个的,但是具体加载哪一个呢?
audio.primary.default.so audio.primary.msm8909.so
AudioFlinger开始的调用流程:
audio_module_handle_t AudioFlinger::loadHwModule(const char *name) |——audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name) |——static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
static int 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);//"audio" hal操作句柄,根据这个去加载hal,if_name为“primary” ALOGE_IF(rc, "%s couldn't load audio hw module %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc)); if (rc) { goto out; } rc = audio_hw_device_open(mod, dev);//操作HAL的adev_open函数 ALOGE_IF(rc, "%s couldn't open audio hw device in %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc)); if (rc) { goto out; } if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) { ALOGE("%s wrong audio hw device version x", __func__, (*dev)->common.version); rc = BAD_VALUE; goto out; } return 0; out: *dev = NULL; return rc; }hardware/libhardware/hardware.c
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); else strlcpy(name, class_id, PATH_MAX); //从上面传下来的name值就是 "audio.primary" /* * 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);//查找属性值是否“ro.hardware.audio.primary” 这个属性值其实并没有设置 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++) { //鉴于上面的属性值并没有找到,就去查找数组variant_keys是否有相关设置 /* 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" }; */ if (property_get(variant_keys[i], prop, NULL) == 0) { continue; //如果当前遍历属性值没有设置,开启查找下一个属性值 } if (hw_module_exists(path, sizeof(path), name, prop) == 0) { //hw_module_exists实质是加上路径查找指定的库 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); }那么以下属性值是在哪里赋值的呢
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” }; “ro.hardware.%s”
以当前所操作的机器来看:
[ro.hardware]: [qcom] [ro.product.board]: [msm8909] [ro.board.platform]: [msm8909] “ro.arch” 没有被设置 ro.hardware.audio.primary 没有被设置
build/tools/buildinfo.sh中间: echo “ro.board.platform=$TARGET_BOARD_PLATFORM”
device/jrdcom/projectname/BoardConfig.mk中间赋值: TARGET_BOARD_PLATFORM := msm8909
到这里就很清楚了 AudioPolicyManager初始化的时候,通过如下代码,根据指定的配置文件加载相应的audio hal库文件:
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice, speakerDrcEnabled, static_cast<VolumeCurvesCollection *>(mVolumeCurves)); PolicySerializer serializer; if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) { //AUDIO_POLICY_XML_CONFIG_FILE "/system/etc/audio_policy_configuration.xml" 。。。 }最后,附上加载函数:
/** * Load the file defined by the variant and if successful * return the dlopen handle and the hmi. * @return 0 = success, !0 = failure. */ static int load(const char *id, const char *path, const struct hw_module_t **pHmi) { int status = -EINVAL; void *handle = NULL; struct hw_module_t *hmi = NULL; /* * load the symbols resolving undefined symbols before * dlopen returns. Since RTLD_GLOBAL is not or'd in with * RTLD_NOW the external symbols will not be global */ handle = dlopen(path, RTLD_NOW);//操作文件 if (handle == NULL) { char const *err_str = dlerror(); ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown"); status = -EINVAL; goto done; } /* Get the address of the struct hal_module_info. */ const char *sym = HAL_MODULE_INFO_SYM_AS_STR; hmi = (struct hw_module_t *)dlsym(handle, sym); if (hmi == NULL) { ALOGE("load: couldn't find symbol %s", sym); status = -EINVAL; goto done; } /* Check that the id matches */ if (strcmp(id, hmi->id) != 0) { ALOGE("load: id=%s != hmi->id=%s", id, hmi->id); status = -EINVAL; goto done; } hmi->dso = handle; /* success */ status = 0; done: if (status != 0) { hmi = NULL; if (handle != NULL) { dlclose(handle); handle = NULL; } } else { ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle); } *pHmi = hmi; return status; }