Merge "hal: Enable support for Listen voice wakeup feature"
diff --git a/hal/Android.mk b/hal/Android.mk
index 6a8da10..44e6862 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -84,6 +84,12 @@
$(LOCAL_PATH)/$(AUDIO_PLATFORM) \
$(LOCAL_PATH)/audio_extn
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_LISTEN)),true)
+ LOCAL_CFLAGS += -DAUDIO_LISTEN_ENABLED
+ LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-listen
+ LOCAL_SRC_FILES += audio_extn/listen.c
+endif
+
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 2389f00..98765c4 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -196,6 +196,7 @@
audio_extn_set_anc_parameters(parms);
audio_extn_set_afe_proxy_parameters(parms);
audio_extn_fm_set_parameters(adev, parms);
+ audio_extn_listen_set_parameters(adev, parms);
}
void audio_extn_get_parameters(const struct audio_device *adev,
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 3676c08..71b4863 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -93,4 +93,28 @@
char *device_name);
#endif
+#ifndef AUDIO_LISTEN_ENABLED
+
+#define audio_extn_listen_init(adev) (0)
+#define audio_extn_listen_deinit(adev) (0)
+#define audio_extn_listen_update_status(uc_info, event) (0)
+#define audio_extn_listen_set_parameters(adev, parms) (0)
+
+#else
+
+enum listen_event_type {
+ LISTEN_EVENT_AUDIO_CAPTURE_INACTIVE,
+ LISTEN_EVENT_AUDIO_CAPTURE_ACTIVE,
+};
+typedef enum listen_event_type listen_event_type_t;
+
+int audio_extn_listen_init(struct audio_device *adev);
+void audio_extn_listen_deinit(struct audio_device *adev);
+void audio_extn_listen_update_status(struct audio_usecase *uc_info,
+ listen_event_type_t event);
+void audio_extn_listen_set_parameters(struct audio_device *adev,
+ struct str_parms *parms);
+
+#endif /* AUDIO_LISTEN_ENABLED */
+
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/listen.c b/hal/audio_extn/listen.c
new file mode 100644
index 0000000..14a427b
--- /dev/null
+++ b/hal/audio_extn/listen.c
@@ -0,0 +1,185 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "listen_hal_loader"
+#define LOG_NDEBUG 0
+/* #define LOG_NDDEBUG 0 */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <cutils/log.h>
+#ifdef AUDIO_LISTEN_ENABLED
+#include <listen_types.h>
+#endif
+#include "audio_hw.h"
+#include "audio_extn.h"
+#include "platform.h"
+#include "platform_api.h"
+
+
+#ifdef AUDIO_LISTEN_ENABLED
+
+#define LIB_LISTEN_LOADER "/vendor/lib/liblistenhardware.so"
+
+#define LISTEN_LOAD_SYMBOLS(dev, func_p, func_type, symbol) \
+{\
+ dev->func_p = (func_type)dlsym(dev->lib_handle,#symbol);\
+ if (dev->func_p == NULL) {\
+ ALOGE("%s: dlsym error %s for %s",\
+ __func__, dlerror(), #symbol);\
+ free(dev);\
+ dev = NULL;\
+ return -EINVAL;\
+ }\
+}
+
+
+typedef int (*create_listen_hw_t)();
+typedef void (*destroy_listen_hw_t)();
+
+typedef int (*open_listen_session_t)(struct audio_hw_device *,
+ struct listen_session**);
+
+typedef int (*close_listen_session_t)(struct audio_hw_device *dev,
+ struct listen_session* handle);
+
+typedef int (*set_mad_observer_t)(struct audio_hw_device *dev,
+ listen_callback_t cb_func);
+
+typedef int (*listen_set_parameters_t)(struct audio_hw_device *dev,
+ const char *kv_pairs);
+typedef char* (*get_parameters_t)(const struct audio_hw_device *dev,
+ const char *keys);
+typedef void (*listen_notify_event_t)(event_type_t event_type);
+
+struct listen_audio_device {
+ void *lib_handle;
+ struct audio_device *adev;
+
+ create_listen_hw_t create_listen_hw;
+ destroy_listen_hw_t destroy_listen_hw;
+ open_listen_session_t open_listen_session;
+ close_listen_session_t close_listen_session;
+ set_mad_observer_t set_mad_observer;
+ listen_set_parameters_t listen_set_parameters;
+ get_parameters_t get_parameters;
+ listen_notify_event_t notify_event;
+};
+
+static struct listen_audio_device *listen_dev;
+
+void audio_extn_listen_update_status(struct audio_usecase *uc_info,
+ listen_event_type_t event)
+{
+ if (listen_dev) {
+ ALOGI("%s(): current active device = %s. Event = %u", __func__,
+ platform_get_snd_device_name(uc_info->in_snd_device),
+ event);
+ if (uc_info->in_snd_device != SND_DEVICE_IN_CAPTURE_FM)
+ listen_dev->notify_event(event);
+ }
+}
+
+void audio_extn_listen_set_parameters(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ return;
+}
+
+int audio_extn_listen_init(struct audio_device *adev)
+{
+ int ret;
+ void *lib_handle;
+
+ ALOGI("%s: Enter", __func__);
+
+ lib_handle = dlopen(LIB_LISTEN_LOADER, RTLD_NOW);
+
+ if (lib_handle == NULL) {
+ ALOGE("%s: DLOPEN failed for %s. error = %s", __func__, LIB_LISTEN_LOADER,
+ dlerror());
+ return -EINVAL;
+ } else {
+ ALOGI("%s: DLOPEN successful for %s", __func__, LIB_LISTEN_LOADER);
+
+ listen_dev = (struct listen_audio_device*)
+ calloc(1, sizeof(struct listen_audio_device));
+
+ listen_dev->lib_handle = lib_handle;
+ listen_dev->adev = adev;
+
+ LISTEN_LOAD_SYMBOLS(listen_dev, create_listen_hw,
+ create_listen_hw_t, create_listen_hw);
+
+ LISTEN_LOAD_SYMBOLS(listen_dev, destroy_listen_hw,
+ destroy_listen_hw_t, destroy_listen_hw);
+
+ LISTEN_LOAD_SYMBOLS(listen_dev, open_listen_session,
+ open_listen_session_t, open_listen_session);
+
+ adev->device.open_listen_session = listen_dev->open_listen_session;
+
+ LISTEN_LOAD_SYMBOLS(listen_dev, close_listen_session,
+ close_listen_session_t, close_listen_session);
+
+ adev->device.close_listen_session = listen_dev->close_listen_session;
+
+ LISTEN_LOAD_SYMBOLS(listen_dev, set_mad_observer,
+ set_mad_observer_t, set_mad_observer);
+
+ adev->device.set_mad_observer = listen_dev->set_mad_observer;
+
+ LISTEN_LOAD_SYMBOLS(listen_dev, listen_set_parameters,
+ listen_set_parameters_t, listen_hw_set_parameters);
+
+ adev->device.listen_set_parameters = listen_dev->listen_set_parameters;
+
+ LISTEN_LOAD_SYMBOLS(listen_dev, get_parameters,
+ get_parameters_t, listen_hw_get_parameters);
+
+ LISTEN_LOAD_SYMBOLS(listen_dev, notify_event,
+ listen_notify_event_t, listen_hw_notify_event);
+
+ listen_dev->create_listen_hw();
+ }
+ return 0;
+}
+
+void audio_extn_listen_deinit(struct audio_device *adev)
+{
+ ALOGI("%s: Enter", __func__);
+
+ if (listen_dev && (listen_dev->adev == adev) && listen_dev->lib_handle) {
+ listen_dev->destroy_listen_hw();
+ dlclose(listen_dev->lib_handle);
+ free(listen_dev);
+ listen_dev = NULL;
+ }
+}
+
+#endif /* AUDIO_LISTEN_ENABLED */
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index b53892f..59e7c86 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -135,7 +135,8 @@
static struct audio_device *adev = NULL;
static pthread_mutex_t adev_init_lock;
-static bool is_adev_initialised = false;
+static unsigned int audio_device_ref_count;
+
static int set_voice_volume_l(struct audio_device *adev, float volume);
static bool is_supported_format(audio_format_t format)
@@ -694,6 +695,9 @@
/* 2. Disable the tx device */
disable_snd_device(adev, uc_info->in_snd_device, true);
+ audio_extn_listen_update_status(uc_info,
+ LISTEN_EVENT_AUDIO_CAPTURE_INACTIVE);
+
list_remove(&uc_info->list);
free(uc_info);
@@ -738,6 +742,9 @@
list_add_tail(&adev->usecase_list, &uc_info->list);
select_devices(adev, in->usecase);
+ audio_extn_listen_update_status(uc_info,
+ LISTEN_EVENT_AUDIO_CAPTURE_ACTIVE);
+
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
__func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
@@ -2289,10 +2296,21 @@
static int adev_close(hw_device_t *device)
{
struct audio_device *adev = (struct audio_device *)device;
- audio_route_free(adev->audio_route);
- free(adev->snd_dev_ref_cnt);
- platform_deinit(adev->platform);
- free(device);
+
+ if (!adev)
+ return 0;
+
+ pthread_mutex_lock(&adev_init_lock);
+
+ if ((--audio_device_ref_count) == 0) {
+ audio_route_free(adev->audio_route);
+ free(adev->snd_dev_ref_cnt);
+ platform_deinit(adev->platform);
+ audio_extn_listen_deinit(adev);
+ free(device);
+ adev = NULL;
+ }
+ pthread_mutex_unlock(&adev_init_lock);
return 0;
}
@@ -2305,8 +2323,9 @@
if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
pthread_mutex_lock(&adev_init_lock);
- if (is_adev_initialised == true){
+ if (audio_device_ref_count != 0){
*device = &adev->device.common;
+ audio_device_ref_count++;
ALOGD("%s: returning existing instance of adev", __func__);
ALOGD("%s: exit", __func__);
pthread_mutex_unlock(&adev_init_lock);
@@ -2374,11 +2393,11 @@
"visualizer_hal_stop_output");
}
}
+ audio_extn_listen_init(adev);
*device = &adev->device.common;
- /* update init flag*/
- is_adev_initialised = true;
+ audio_device_ref_count++;
pthread_mutex_unlock(&adev_init_lock);
ALOGV("%s: exit", __func__);
diff --git a/hal/voice.c b/hal/voice.c
index 39e2dd9..907ebc9 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -31,6 +31,7 @@
#include "voice_extn/voice_extn.h"
#include "platform.h"
#include "platform_api.h"
+#include "audio_extn.h"
struct pcm_config pcm_config_voice_call = {
.channels = 1,
@@ -106,6 +107,9 @@
disable_snd_device(adev, uc_info->out_snd_device, false);
disable_snd_device(adev, uc_info->in_snd_device, true);
+ audio_extn_listen_update_status(uc_info,
+ LISTEN_EVENT_AUDIO_CAPTURE_INACTIVE);
+
list_remove(&uc_info->list);
free(uc_info);
@@ -136,6 +140,9 @@
select_devices(adev, usecase_id);
+ audio_extn_listen_update_status(uc_info,
+ LISTEN_EVENT_AUDIO_CAPTURE_ACTIVE);
+
pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);