Audio (1) -AudioFlinger loading audio module process

Device interface currently supports Android4.2 are the following (defined in AudioFlinger.cpp):

1 static const char * const audio_interfaces[] = {
2    AUDIO_HARDWARE_MODULE_ID_PRIMARY, //The main audio equipment, must exist
3    AUDIO_HARDWARE_MODULE_ID_A2DP, //Bluetooth A2DP audio
4    AUDIO_HARDWARE_MODULE_ID_USB, //USB audio, early version is not supported
5 };

Array of const is defined in the /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 in the initialization, and does not take the initiative to load the audio module, it provides a loadHwModule (const char *name) interface to the AudioPolicyService call, name is one of several devices support. Following a primary device as an example:

  1. The loadHwModule method is simple and is locked, call loadHwModule_l (const char *name) method
  2. Load_audio_interface calls the loadHwModule_l method to complete the actual loading operation, the name passed, that is“primary”
  3. A general loading module interface libhardware calls the load_audio_interface method provides: 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; }

The parameter Inst is “ primary&rdquo, class_id; AUDIO_HARDWARE_MODULE_ID, defined in the audio.h:

#define AUDIO_HARDWARE_MODULE_ID "audio"

This method will traverse the variant_keys array:

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"
};

In system property, via the key value, in accordance with the order will pass over the primary together, find the corresponding *.so file exists.

For example, our company's platform, the first two property for array in null, and ro.board.platform for “ mrvl”, then assembled by the so file name: audio.primary.mrvl.so.

Then the search in two different directory:

/** Base path of the hal modules */
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

  4 then call the load function, open the *.so.

Posted by Gavin at November 19, 2013 - 10:10 AM