Audio(1)-AudioFlinger加载audio module过程_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > Audio(1)-AudioFlinger加载audio module过程

Audio(1)-AudioFlinger加载audio module过程

 2013/8/18 19:28:55  coding4范儿  博客园  我要评论(0)
  • 摘要:Android4.2中目前支持的设备接口有以下几种(定义在AudioFlinger.cpp):1staticconstchar*constaudio_interfaces[]={2AUDIO_HARDWARE_MODULE_ID_PRIMARY,//主音频设备,必须存在3AUDIO_HARDWARE_MODULE_ID_A2DP,//蓝牙A2DP音频4AUDIO_HARDWARE_MODULE_ID_USB,//USB音频,早期的版本不支持5}
  • 标签:过程

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设备为例:

  1. loadHwModule方法简单加锁后,调用loadHwModule_l(const char *name)方法
  2. loadHwModule_l方法调用load_audio_interface来完成实际的加载操作,把name传递过去,也就是“primary”
  3. load_audio_interface方法调用libhardware提供的一个通用的加载module接口:hw_get_module_by_class
// 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。

发表评论
用户名: 匿名