hal: add support for external speaker driver library
Change-Id: I599c96793097ab6202412cbd55c8e9165c226eed
Bug: 17319721
diff --git a/hal/Android.mk b/hal/Android.mk
index a1ff948..18b8bf4 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -22,6 +22,7 @@
audio_hw.c \
voice.c \
platform_info.c \
+ audio_extn/ext_speaker.c \
$(AUDIO_PLATFORM)/platform.c
LOCAL_SHARED_LIBRARIES := \
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index efa63aa..6009366 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -19,6 +19,11 @@
#include <cutils/str_parms.h>
+void *audio_extn_extspk_init(struct audio_device *adev);
+void audio_extn_extspk_deinit(void *extn);
+void audio_extn_extspk_update(void* extn);
+void audio_extn_extspk_set_mode(void* extn, audio_mode_t mode);
+
#ifndef HFP_ENABLED
#define audio_extn_hfp_is_active(adev) (0)
#define audio_extn_hfp_get_usecase() (-1)
diff --git a/hal/audio_extn/ext_speaker.c b/hal/audio_extn/ext_speaker.c
new file mode 100644
index 0000000..611e916
--- /dev/null
+++ b/hal/audio_extn/ext_speaker.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ext_speaker"
+/*#define LOG_NDEBUG 0*/
+#include <cutils/log.h>
+
+#include <audio_hw.h>
+#include <dlfcn.h>
+
+#ifdef __LP64__
+ #define LIB_SPEAKER_BUNDLE "/system/lib64/soundfx/libspeakerbundle.so"
+#else
+ #define LIB_SPEAKER_BUNDLE "/system/lib/soundfx/libspeakerbundle.so"
+#endif
+
+typedef void (*set_mode_t)(int);
+typedef void (*set_speaker_on_t)(bool);
+typedef void (*set_earpiece_on_t)(bool);
+typedef void (*set_voice_vol_t)(int);
+
+struct speaker_data {
+ struct audio_device *adev;
+ void *speaker_bundle;
+ set_mode_t set_mode;
+ set_speaker_on_t set_speaker_on;
+ set_earpiece_on_t set_earpiece_on;
+ set_voice_vol_t set_voice_vol;
+};
+
+static struct speaker_data* open_speaker_bundle()
+{
+ struct speaker_data *sd = calloc(1, sizeof(struct speaker_data));
+
+ sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW);
+ if (sd->speaker_bundle == NULL) {
+ ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE);
+ goto error;
+ } else {
+ ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE);
+
+ sd->set_mode = (set_mode_t)dlsym(sd->speaker_bundle,
+ "set_mode");
+ if (sd->set_mode == NULL) {
+ ALOGE("%s: dlsym error %s for set_mode", __func__,
+ dlerror());
+ goto error;
+ }
+ sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle,
+ "set_speaker_on");
+ if (sd->set_speaker_on == NULL) {
+ ALOGE("%s: dlsym error %s for set_speaker_on", __func__,
+ dlerror());
+ goto error;
+ }
+ sd->set_earpiece_on = (set_earpiece_on_t)dlsym(sd->speaker_bundle,
+ "set_earpiece_on");
+ if (sd->set_earpiece_on == NULL) {
+ ALOGE("%s: dlsym error %s for set_earpiece_on", __func__,
+ dlerror());
+ goto error;
+ }
+ sd->set_voice_vol = (set_voice_vol_t)dlsym(sd->speaker_bundle,
+ "set_voice_volume");
+ if (sd->set_voice_vol == NULL) {
+ ALOGE("%s: dlsym error %s for set_voice_volume",
+ __func__, dlerror());
+ goto error;
+ }
+ }
+ return sd;
+
+error:
+ free(sd);
+ return 0;
+}
+
+static void close_speaker_bundle(struct speaker_data *sd)
+{
+ if (sd != NULL) {
+ dlclose(sd->speaker_bundle);
+ free(sd);
+ sd = NULL;
+ }
+}
+
+void *audio_extn_extspk_init(struct audio_device *adev)
+{
+ struct speaker_data *data = open_speaker_bundle();
+
+ if (data)
+ data->adev = adev;
+
+ return data;
+}
+
+void audio_extn_extspk_deinit(void *extn)
+{
+ struct speaker_data *data = (struct speaker_data*)extn;
+ close_speaker_bundle(data);
+}
+
+void audio_extn_extspk_update(void* extn)
+{
+ struct speaker_data *data = (struct speaker_data*)extn;
+
+ if (data) {
+ bool speaker_on = false;
+ bool earpiece_on = false;
+ struct listnode *node;
+ struct audio_usecase *usecase;
+ list_for_each(node, &data->adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ if (usecase->devices & AUDIO_DEVICE_OUT_EARPIECE) {
+ if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
+ earpiece_on = true;
+ }
+ }
+ if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) {
+ if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
+ speaker_on = true;
+ }
+ }
+ }
+ data->set_earpiece_on(earpiece_on);
+ data->set_speaker_on(speaker_on);
+ }
+}
+
+void audio_extn_extspk_set_mode(void* extn, audio_mode_t mode)
+{
+ struct speaker_data *data = (struct speaker_data*)extn;
+
+ if (data)
+ data->set_mode(mode);
+}
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1fee1d3..9908b81 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1005,6 +1005,8 @@
list_remove(&uc_info->list);
free(uc_info);
+ audio_extn_extspk_update(adev->extspk);
+
/* Must be called after removing the usecase from list */
if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
@@ -1045,6 +1047,8 @@
select_devices(adev, out->usecase);
+ audio_extn_extspk_update(adev->extspk);
+
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
__func__, adev->snd_card, out->pcm_device_id, out->config.format);
if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -1353,6 +1357,9 @@
pthread_mutex_unlock(&adev->lock);
pthread_mutex_unlock(&out->lock);
+
+ /*handles device and call state changes*/
+ audio_extn_extspk_update(adev->extspk);
}
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -2280,6 +2287,9 @@
adev->mode = mode;
}
pthread_mutex_unlock(&adev->lock);
+
+ audio_extn_extspk_set_mode(adev->extspk, mode);
+
return 0;
}
@@ -2566,6 +2576,7 @@
audio_route_free(adev->audio_route);
free(adev->snd_dev_ref_cnt);
platform_deinit(adev->platform);
+ audio_extn_extspk_deinit(adev->extspk);
for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
pcm_params_free(adev->use_case_table[i]);
}
@@ -2649,6 +2660,8 @@
return -EINVAL;
}
+ adev->extspk = audio_extn_extspk_init(adev);
+
if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
if (adev->visualizer_lib == NULL) {
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 251a055..c45cb74 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -214,6 +214,7 @@
int snd_card;
void *platform;
+ void *extspk;
void *visualizer_lib;
int (*visualizer_start_output)(audio_io_handle_t, int);