Android4.2中目前支持的设备接口有以下几种(定义在AudioFlinger.cpp):
1 static const char * const audio_interfaces[] = { 2 AUDIO_HARDWARE_MODULE_ID_PRIMARY, //主音频设备,必须存在 3 AUDIO_HARDWARE_MODULE_ID_A2DP, //蓝牙A2DP音频 4 AUDIO_HARDWARE_MODULE_ID_USB, //USB音频,早期的版本不支持 5 };
数组中的常量又定义在/hardware/libhardware/include/audio.h中:
#define AUDIO_HARDWARE_MODULE_ID_PRIMARY "primary" #define AUDIO_HARDWARE_MODULE_ID_A2DP "a2dp" #define AUDIO_HARDWARE_MODULE_ID_USB "usb"
AudioFlinger在初始化时,并不会主动去加载audio module,它提供了一个loadHwModule(const char *name)接口给AudioPolicyService调用,name就是支持的几种设备之一。以下一primary设备为例:
// path: libhardware/hardware.c
int hw_get_module_by_class(const char *class_id, const char *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); 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. */ /* 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) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH2, name, prop); if (access(path, R_OK) == 0) break; snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH1, name, prop); if (access(path, R_OK) == 0) break; } else { snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH1, name); if (access(path, R_OK) == 0) break; } } 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; }
其中的参数inst就是“primary”,class_id为AUDIO_HARDWARE_MODULE_ID,定义在audio.h中:
#define AUDIO_HARDWARE_MODULE_ID "audio"
这个方法会遍历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" };
在system property中,取道以这些为key的值,按照顺序将传递过来的primary拼接起来,查找对应的*.so文件是否存在。
比如我们公司的平台,数组中前两个property都为null,而ro.board.platform为“mrvl”,那么就拼接得到这个so文件的名称:audio.primary.mrvl.so。
然后在两个不同的目录下搜索:
/** Base path of the hal modules */ #define HAL_LIBRARY_PATH1 "/system/lib/hw" #define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
4.然后调用load函数,打开这个*.so。