Android AudioFlinger加载HAL层流程

一、前提

Audio HAL层最终以.so的方式为Android所用,那这个.so的库如何被AudioFlinger所使用?

二、Audio Hardware HAL加载

(1)AudioFlinger

AudioFlinger加载HAL层:

*if_name, const hw_module_t **mod,audio_hw_device_t **dev) {int rc;/* 这里加载的是音频动态库,如audio.primary.msm8916.so,如何加载会独立体现 */rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);if (rc)goto out;//加载好的动态库模块必有个open方法,调用open方法打开音频设备模块 rc = audio_hw_device_open(*mod, dev);LOGE_IF(rc, “couldn’t open audio hw device in %s.%s (%s)”,AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));if (rc)goto out;return 0; out:*mod = NULL;*dev = NULL;return rc; }

audio_interface:

*audio_interfaces[] = {,//usb-audio设备 };

AudioFlinger::onFirstRef:

void AudioFlinger::onFirstRef() {int rc = 0;Mutex::Autolock _l(mLock);/* TODO: move all this work into an Init() function */mHardwareStatus = AUDIO_HW_IDLE;//打开audio_interfaces数组定义的所有音频设备 for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {const hw_module_t *mod;audio_hw_device_t *dev;rc = load_audio_interface(audio_interfaces[i], &mod, &dev);if (rc)continue;LOGI(“Loaded %s audio interface from %s (%s)”, audio_interfaces[i],mod->name, mod->id);mAudioHwDevs.push(dev); //mAudioHwDevs是一个Vector,存储已打开的audio hw devices if (!mPrimaryHardwareDev) {mPrimaryHardwareDev = dev;LOGI(“Using ‘%s’ (%s.%s) as the primary audio interface”,mod->name, mod->id, audio_interfaces[i]);}}mHardwareStatus = AUDIO_HW_INIT;if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) {LOGE(“Primary audio interface not found”);return;}//对audio hw devices进行一些初始化,如mode、master volume的设置 for (size_t i = 0; i < mAudioHwDevs.size(); i++) {audio_hw_device_t *dev = mAudioHwDevs[i];mHardwareStatus = AUDIO_HW_INIT;rc = dev->init_check(dev);if (rc == 0) {AutoMutex lock(mHardwareLock);mMode = AUDIO_MODE_NORMAL;mHardwareStatus = AUDIO_HW_SET_MODE;dev->set_mode(dev, mMode);mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;dev->set_master_volume(dev, 1.0f);mHardwareStatus = AUDIO_HW_IDLE;}} }

主要是通过hw_get_module_by_class()找到模块接口名字if_name相匹配的模块库,加载之后audio_hw_device_open()调用模块的open方法,完成音频设备模块的初始化。

hw_get_module_by_class:

hw_get_module_by_class实现在hardware/libhardware/ hardware.c中,它作用加载指定名字的模块库(.so文件)。

*inst,const struct hw_module_t **module) {int status;int i;const struct hw_module_t *hmi = NULL;char prop[PATH_MAX];char path[PATH_MAX];char name[PATH_MAX];if (inst)snprintf(name, PATH_MAX, “%s.%s”, class_id, inst);elsestrlcpy(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.*//* Loop through the configuration variants looking for a module */for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {if (i < HAL_VARIANT_KEYS_COUNT) {/* 通过property_get找到厂家标记如”ro.product.board=msm8916″,这时prop=”msm8916″ */if (property_get(variant_keys[i], prop, NULL) == 0) {continue;}/* #define HAL_LIBRARY_PATH2 “/vendor/lib/hw” */snprintf(path, sizeof(path), “%s/%s.%s.so”,HAL_LIBRARY_PATH2, name, prop);if (access(path, R_OK) == 0) break;/* #define HAL_LIBRARY_PATH1 “/system/lib/hw” */snprintf(path, sizeof(path), “%s/%s.%s.so”,HAL_LIBRARY_PATH1, name, prop);if (access(path, R_OK) == 0) break;} else {/* 如没有指定的库文件,则加载default.so */snprintf(path, sizeof(path), “%s/%s.default.so”,HAL_LIBRARY_PATH1, name);if (access(path, R_OK) == 0) break;}}/** 到这里,完成一个模块库的完整路径名称,如path=”/system/lib/hw/audio.primary.msm8916.so” */status = -ENOENT;if (i < HAL_VARIANT_KEYS_COUNT+1) {/* load the module, if this fails, we’re doomed, and we should not try* to load a different variant. *///加载模块库:见下面status = load(class_id, path, module);}return status; } 都成为命途中美丽的点缀,看天,看雪,安安静静,不言不语都是好风景。

Android AudioFlinger加载HAL层流程

相关文章:

你感兴趣的文章:

标签云: