129 lines
3.1 KiB
C
129 lines
3.1 KiB
C
|
|
#define LOG_TAG "audio_client"
|
|
|
|
#include <string.h>
|
|
#include <dlfcn.h>
|
|
#include <hardware/hardware.h>
|
|
#include <hardware/audio.h>
|
|
#include <pthread.h>
|
|
#include "aml_audio_log.h"
|
|
|
|
#include "audio_if.h"
|
|
|
|
#define AUDIO_HAL_LIB "libaudio_hal.so"
|
|
static pthread_mutex_t if_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
static int if_ref_cnt;
|
|
static audio_hw_device_t *hw_dev;
|
|
|
|
static int load(const char *id,
|
|
const char *path,
|
|
struct hw_module_t **pHmi)
|
|
{
|
|
int status = -EINVAL;
|
|
void *handle = NULL;
|
|
struct hw_module_t *hmi = NULL;
|
|
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
|
|
|
|
handle = dlopen(path, RTLD_NOW);
|
|
if (!handle) {
|
|
const char *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. */
|
|
hmi = (struct hw_module_t *)dlsym(handle, sym);
|
|
if (!hmi) {
|
|
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 {
|
|
ALOGE("loaded HAL id=%s path=%s hmi=%p handle=%p",
|
|
id, path, *pHmi, handle);
|
|
}
|
|
|
|
*pHmi = hmi;
|
|
|
|
return status;
|
|
}
|
|
|
|
int audio_hw_load_interface(audio_hw_device_t **dev)
|
|
{
|
|
int r;
|
|
struct hw_module_t *pHmi = NULL;
|
|
|
|
pthread_mutex_lock(&if_mutex);
|
|
ALOGI("%s, %d: enter.", __func__, __LINE__);
|
|
if (if_ref_cnt) {
|
|
*dev = hw_dev;
|
|
if_ref_cnt++;
|
|
pthread_mutex_unlock(&if_mutex);
|
|
return 0;
|
|
}
|
|
|
|
r = load(AUDIO_HARDWARE_MODULE_ID, AUDIO_HAL_LIB, &pHmi);
|
|
if (r) {
|
|
ALOGE("audio_hw_load_module couldn't load audio_hal module");
|
|
goto out;
|
|
}
|
|
|
|
r = pHmi->methods->open(pHmi, AUDIO_HARDWARE_INTERFACE,
|
|
(struct hw_device_t**)dev);
|
|
if (r) {
|
|
ALOGE("audio_hw_load_module couldn't open device");
|
|
goto out;
|
|
}
|
|
if_ref_cnt++;
|
|
hw_dev = *dev;
|
|
pthread_mutex_unlock(&if_mutex);
|
|
return 0;
|
|
|
|
out:
|
|
*dev = NULL;
|
|
pthread_mutex_unlock(&if_mutex);
|
|
return r;
|
|
}
|
|
|
|
void audio_hw_unload_interface(audio_hw_device_t *dev)
|
|
{
|
|
struct hw_module_t *pHmi = dev->common.module;
|
|
int ret = 0;
|
|
pthread_mutex_lock(&if_mutex);
|
|
ALOGI("%s, %d: enter ref (%d)", __func__, __LINE__, if_ref_cnt);
|
|
if (if_ref_cnt > 1)
|
|
if_ref_cnt--;
|
|
if (if_ref_cnt == 0 && pHmi) {
|
|
ret = dev->common.close((struct hw_device_t*)dev);
|
|
if (ret)
|
|
ALOGE("%s, failed to close audio_hal module.\n", __FUNCTION__);
|
|
ret = dlclose(pHmi->dso);
|
|
if (ret)
|
|
ALOGE("%s, failed to close audio_hal module:%s\n", __FUNCTION__, dlerror());
|
|
pHmi = NULL;
|
|
hw_dev = NULL;
|
|
}
|
|
pthread_mutex_unlock(&if_mutex);
|
|
}
|