Revert "Revert "hal: Notify soundtrigger HAL on stream updates""
This reverts commit 9fc06a06405277a54a56859fd68ea9c9b8e3786d.
Instead of sending device enable/disable events, send use case
enable/disable events with use case type to sound trigger hal.
Playback (on speaker) and capture stream events are updated
to soundtrigger hal.
Sound trigger hal can decide to support concurrent sountrigger
sessions based on the audio use case.
Also avoid compilation dependency on sound trigger hal proprietary
interface header file by maintaining the interface APIs locally.
Bug: 63939932
Test: "ok google" from lock screen on marlin, sailfish, walleye,
taimen,
music iq on walleye and taimen
Change-Id: I16422b85b929774373f7000f5b6167086340a6df
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 2ca76fa..12fe04d 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -107,6 +107,7 @@
#define audio_extn_sound_trigger_init(adev) (0)
#define audio_extn_sound_trigger_deinit(adev) (0)
#define audio_extn_sound_trigger_update_device_status(snd_dev, event) (0)
+#define audio_extn_sound_trigger_update_stream_status(uc_info, event) (0)
#define audio_extn_sound_trigger_set_parameters(adev, parms) (0)
#define audio_extn_sound_trigger_check_and_get_session(in) (0)
#define audio_extn_sound_trigger_stop_lab(in) (0)
@@ -126,6 +127,8 @@
void audio_extn_sound_trigger_deinit(struct audio_device *adev);
void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device,
st_event_type_t event);
+void audio_extn_sound_trigger_update_stream_status(struct audio_usecase *uc_info,
+ st_event_type_t event);
void audio_extn_sound_trigger_set_parameters(struct audio_device *adev,
struct str_parms *parms);
void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in);
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index 111f9a2..c11e747 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -28,17 +28,121 @@
#include "audio_extn.h"
#include "platform.h"
#include "platform_api.h"
-#include "sound_trigger_prop_intf.h"
+
+/*-------------------- Begin: AHAL-STHAL Interface ---------------------------*/
+/*
+ * Maintain the proprietary interface between AHAL and STHAL locally to avoid
+ * the compilation dependency of interface header file from STHAL.
+ */
+
+#define MAKE_HAL_VERSION(maj, min) ((((maj) & 0xff) << 8) | ((min) & 0xff))
+#define MAJOR_VERSION(ver) (((ver) & 0xff00) >> 8)
+#define MINOR_VERSION(ver) ((ver) & 0x00ff)
+
+/* Proprietary interface version used for compatibility with STHAL */
+#define STHAL_PROP_API_VERSION_1_0 MAKE_HAL_VERSION(1, 0)
+#define STHAL_PROP_API_CURRENT_VERSION STHAL_PROP_API_VERSION_1_0
+
+#define ST_EVENT_CONFIG_MAX_STR_VALUE 32
+
+typedef enum {
+ ST_EVENT_SESSION_REGISTER,
+ ST_EVENT_SESSION_DEREGISTER
+} sound_trigger_event_type_t;
+
+typedef enum {
+ AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE,
+ AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE,
+ AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE,
+ AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE,
+ AUDIO_EVENT_STOP_LAB,
+ AUDIO_EVENT_SSR,
+ AUDIO_EVENT_NUM_ST_SESSIONS,
+ AUDIO_EVENT_READ_SAMPLES,
+ AUDIO_EVENT_DEVICE_CONNECT,
+ AUDIO_EVENT_DEVICE_DISCONNECT,
+ AUDIO_EVENT_SVA_EXEC_MODE,
+ AUDIO_EVENT_SVA_EXEC_MODE_STATUS,
+ AUDIO_EVENT_CAPTURE_STREAM_INACTIVE,
+ AUDIO_EVENT_CAPTURE_STREAM_ACTIVE,
+} audio_event_type_t;
+
+typedef enum {
+ USECASE_TYPE_PCM_PLAYBACK,
+ USECASE_TYPE_PCM_CAPTURE,
+ USECASE_TYPE_VOICE_CALL,
+ USECASE_TYPE_VOIP_CALL,
+} audio_stream_usecase_type_t;
+
+typedef enum {
+ SND_CARD_STATUS_OFFLINE,
+ SND_CARD_STATUS_ONLINE,
+ CPE_STATUS_OFFLINE,
+ CPE_STATUS_ONLINE
+} ssr_event_status_t;
+
+struct sound_trigger_session_info {
+ void* p_ses; /* opaque pointer to st_session obj */
+ int capture_handle;
+ struct pcm *pcm;
+ struct pcm_config config;
+};
+
+struct audio_read_samples_info {
+ struct sound_trigger_session_info *ses_info;
+ void *buf;
+ size_t num_bytes;
+};
+
+struct audio_hal_usecase {
+ audio_stream_usecase_type_t type;
+};
+
+struct sound_trigger_event_info {
+ struct sound_trigger_session_info st_ses;
+};
+
+struct audio_event_info {
+ union {
+ ssr_event_status_t status;
+ int value;
+ struct sound_trigger_session_info ses_info;
+ struct audio_read_samples_info aud_info;
+ char str_value[ST_EVENT_CONFIG_MAX_STR_VALUE];
+ struct audio_hal_usecase usecase;
+ }u;
+};
+
+/* STHAL callback which is called by AHAL */
+typedef int (*sound_trigger_hw_call_back_t)(audio_event_type_t,
+ struct audio_event_info*);
+
+/*---------------- End: AHAL-STHAL Interface ----------------------------------*/
#define XSTR(x) STR(x)
#define STR(x) #x
+#define DLSYM(handle, ptr, symbol, err) \
+do { \
+ ptr = dlsym(handle, #symbol); \
+ if (ptr == NULL) { \
+ ALOGE("%s: dlsym %s failed . %s", __func__, #symbol, dlerror()); \
+ err = -ENODEV; \
+ } \
+} while(0)
+
#ifdef __LP64__
-#define SOUND_TRIGGER_LIBRARY_PATH "/system/vendor/lib64/hw/sound_trigger.primary.%s.so"
+#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib64/hw/sound_trigger.primary.%s.so"
#else
-#define SOUND_TRIGGER_LIBRARY_PATH "/system/vendor/lib/hw/sound_trigger.primary.%s.so"
+#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib/hw/sound_trigger.primary.%s.so"
#endif
+/*
+ * Current proprietary API version used by AHAL. Queried by STHAL
+ * for compatibility check with AHAL
+ */
+const unsigned int sthal_prop_api_version = STHAL_PROP_API_CURRENT_VERSION;
+
struct sound_trigger_info {
struct sound_trigger_session_info st_ses;
bool lab_stopped;
@@ -51,6 +155,7 @@
sound_trigger_hw_call_back_t st_callback;
struct listnode st_ses_list;
pthread_mutex_t lock;
+ unsigned int sthal_prop_api_version;
};
static struct sound_trigger_audio_device *st_dev;
@@ -60,7 +165,7 @@
{
struct sound_trigger_info *st_ses_info = NULL;
struct listnode *node;
- ALOGV("%s: list %d capture_handle %d", __func__,
+ ALOGV("%s: list empty %d capture_handle %d", __func__,
list_empty(&st_dev->st_ses_list), capture_handle);
list_for_each(node, &st_dev->st_ses_list) {
st_ses_info = node_to_item(node, struct sound_trigger_info , list);
@@ -70,6 +175,37 @@
return NULL;
}
+static int populate_usecase(struct audio_hal_usecase *usecase,
+ struct audio_usecase *uc_info)
+{
+ int status = 0;
+
+ switch (uc_info->type) {
+ case PCM_PLAYBACK:
+ if (uc_info->id == USECASE_AUDIO_PLAYBACK_VOIP)
+ usecase->type = USECASE_TYPE_VOIP_CALL;
+ else
+ usecase->type = USECASE_TYPE_PCM_PLAYBACK;
+ break;
+
+ case PCM_CAPTURE:
+ if (uc_info->id == USECASE_AUDIO_RECORD_VOIP)
+ usecase->type = USECASE_TYPE_VOIP_CALL;
+ else
+ usecase->type = USECASE_TYPE_PCM_CAPTURE;
+ break;
+
+ case VOICE_CALL:
+ usecase->type = USECASE_TYPE_VOICE_CALL;
+ break;
+
+ default:
+ ALOGE("%s: unsupported usecase type %d", __func__, uc_info->type);
+ status = -EINVAL;
+ }
+ return status;
+}
+
static void stdev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
{
if (!parms)
@@ -80,7 +216,7 @@
}
int audio_hw_call_back(sound_trigger_event_type_t event,
- sound_trigger_event_info_t* config)
+ struct sound_trigger_event_info* config)
{
int status = 0;
struct sound_trigger_info *st_ses_info;
@@ -138,7 +274,7 @@
{
int ret = -1;
struct sound_trigger_info *st_info = NULL;
- audio_event_info_t event;
+ struct audio_event_info event;
if (!st_dev)
return ret;
@@ -174,11 +310,10 @@
void audio_extn_sound_trigger_stop_lab(struct stream_in *in)
{
- int status = 0;
struct sound_trigger_info *st_ses_info = NULL;
- audio_event_info_t event;
+ struct audio_event_info event;
- if (!st_dev || !in)
+ if (!st_dev || !in || !in->is_st_session_active)
return;
pthread_mutex_lock(&st_dev->lock);
@@ -188,8 +323,10 @@
event.u.ses_info = st_ses_info->st_ses;
ALOGV("%s: AUDIO_EVENT_STOP_LAB pcm %p", __func__, st_ses_info->st_ses.pcm);
st_dev->st_callback(AUDIO_EVENT_STOP_LAB, &event);
+ in->is_st_session_active = false;
}
}
+
void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in)
{
struct sound_trigger_info *st_ses_info = NULL;
@@ -225,6 +362,9 @@
if (!st_dev)
return;
+ if (st_dev->sthal_prop_api_version >= STHAL_PROP_API_VERSION_1_0)
+ return;
+
if (snd_device >= SND_DEVICE_OUT_BEGIN &&
snd_device < SND_DEVICE_OUT_END) {
device_type = PCM_PLAYBACK;
@@ -256,10 +396,52 @@
}/*Events for output device, if required can be placed here in else*/
}
+void audio_extn_sound_trigger_update_stream_status(struct audio_usecase *uc_info,
+ st_event_type_t event)
+{
+ bool raise_event = false;
+ struct audio_event_info ev_info;
+ audio_event_type_t ev;
+
+ if (!st_dev)
+ return;
+
+ if (st_dev->sthal_prop_api_version < STHAL_PROP_API_VERSION_1_0)
+ return;
+
+ if (uc_info == NULL) {
+ ALOGE("%s: null usecase", __func__);
+ return;
+ }
+
+ bool valid_type =
+ (uc_info->type == PCM_PLAYBACK &&
+ platform_snd_device_has_speaker(uc_info->out_snd_device)) ||
+ (uc_info->type == PCM_CAPTURE) ||
+ (uc_info->type == VOICE_CALL);
+
+ if (valid_type && platform_sound_trigger_usecase_needs_event(uc_info->id)) {
+ ALOGV("%s: uc_id %d of type %d for Event %d, with Raise=%d",
+ __func__, uc_info->id, uc_info->type, event, raise_event);
+ if (uc_info->type == PCM_CAPTURE) {
+ ev = (event == ST_EVENT_STREAM_BUSY) ? AUDIO_EVENT_CAPTURE_STREAM_ACTIVE :
+ AUDIO_EVENT_CAPTURE_STREAM_INACTIVE;
+ } else {
+ ev = (event == ST_EVENT_STREAM_BUSY) ? AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE :
+ AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE;
+ }
+ if (!populate_usecase(&ev_info.u.usecase, uc_info)) {
+ ALOGI("%s: send event %d: usecase id %d, type %d",
+ __func__, ev, uc_info->id, uc_info->type);
+ st_dev->st_callback(ev, &ev_info);
+ }
+ }
+}
+
void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused,
struct str_parms *params)
{
- audio_event_info_t event;
+ struct audio_event_info event;
char value[32];
int ret, val;
@@ -308,7 +490,7 @@
{
int status = 0;
char sound_trigger_lib[100];
- void *lib_handle;
+ void *sthal_prop_api_version;
ALOGV("%s: Enter", __func__);
@@ -326,20 +508,33 @@
st_dev->lib_handle = dlopen(sound_trigger_lib, RTLD_NOW);
if (st_dev->lib_handle == NULL) {
- ALOGE("%s: DLOPEN failed for %s. error = %s", __func__, sound_trigger_lib,
- dlerror());
- status = -EINVAL;
+ ALOGE("%s: error %s", __func__, dlerror());
+ status = -ENODEV;
goto cleanup;
}
ALOGV("%s: DLOPEN successful for %s", __func__, sound_trigger_lib);
- st_dev->st_callback = (sound_trigger_hw_call_back_t)
- dlsym(st_dev->lib_handle, "sound_trigger_hw_call_back");
+ DLSYM(st_dev->lib_handle, st_dev->st_callback, sound_trigger_hw_call_back,
+ status);
+ if (status)
+ goto cleanup;
- if (st_dev->st_callback == NULL) {
- ALOGE("%s: ERROR. dlsym Error:%s sound_trigger_hw_call_back", __func__,
- dlerror());
- goto cleanup;
+ DLSYM(st_dev->lib_handle, sthal_prop_api_version,
+ sthal_prop_api_version, status);
+ if (status) {
+ st_dev->sthal_prop_api_version = 0;
+ status = 0; /* passthru for backward compability */
+ } else {
+ st_dev->sthal_prop_api_version = *(int*)sthal_prop_api_version;
+ if (MAJOR_VERSION(st_dev->sthal_prop_api_version) !=
+ MAJOR_VERSION(STHAL_PROP_API_CURRENT_VERSION)) {
+ ALOGE("%s: Incompatible API versions ahal:0x%x != sthal:0x%x",
+ __func__, STHAL_PROP_API_CURRENT_VERSION,
+ st_dev->sthal_prop_api_version);
+ goto cleanup;
+ }
+ ALOGD("%s: sthal is using proprietary API version 0x%04x", __func__,
+ st_dev->sthal_prop_api_version);
}
st_dev->adev = adev;
@@ -354,7 +549,6 @@
free(st_dev);
st_dev = NULL;
return status;
-
}
void audio_extn_sound_trigger_deinit(struct audio_device *adev)
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index f2dec25..f586865 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -563,11 +563,11 @@
snd_device = usecase->in_snd_device;
else
snd_device = usecase->out_snd_device;
-
audio_extn_utils_send_app_type_cfg(adev, usecase);
audio_extn_utils_send_audio_calibration(adev, usecase);
strcpy(mixer_path, use_case_table[usecase->id]);
platform_add_backend_name(adev->platform, mixer_path, snd_device);
+ audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
audio_route_apply_and_update_path(adev->audio_route, mixer_path);
@@ -593,6 +593,7 @@
platform_add_backend_name(adev->platform, mixer_path, snd_device);
ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
audio_route_reset_and_update_path(adev->audio_route, mixer_path);
+ audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
ALOGV("%s: exit", __func__);
return 0;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index af48c03..66803bc 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -2457,3 +2457,12 @@
{
return -ENOSYS;
}
+
+bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id __unused)
+{
+ return false;
+}
+
+bool platform_snd_device_has_speaker(snd_device_t dev __unused) {
+ return false;
+}
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index d123646..580f230 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1326,3 +1326,12 @@
{
return -ENOSYS;
}
+
+bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id __unused)
+{
+ return false;
+}
+
+bool platform_snd_device_has_speaker(snd_device_t dev __unused) {
+ return false;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 6a72c60..c1568a7 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -4163,3 +4163,49 @@
return -1;
#endif
}
+
+bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id)
+{
+ bool needs_event = false;
+
+ switch (uc_id) {
+ /* concurrent capture usecases which needs event */
+ case USECASE_AUDIO_RECORD:
+ case USECASE_AUDIO_RECORD_LOW_LATENCY:
+ case USECASE_AUDIO_RECORD_MMAP:
+ case USECASE_AUDIO_RECORD_HIFI:
+ case USECASE_AUDIO_RECORD_VOIP:
+ case USECASE_VOICEMMODE1_CALL:
+ case USECASE_VOICEMMODE2_CALL:
+ /* concurrent playback usecases that needs event */
+ case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD:
+ needs_event = true;
+ break;
+ default:
+ ALOGV("%s:usecase_id[%d] no need to raise event.", __func__, uc_id);
+ }
+ return needs_event;
+}
+
+bool platform_snd_device_has_speaker(snd_device_t dev) {
+ int num_devs = 2;
+ snd_device_t split_devs[2] = {SND_DEVICE_NONE, SND_DEVICE_NONE};
+ if (platform_can_split_snd_device(dev, &num_devs, split_devs) == 0) {
+ return platform_snd_device_has_speaker(split_devs[0]) ||
+ platform_snd_device_has_speaker(split_devs[1]);
+ }
+
+ switch (dev) {
+ case SND_DEVICE_OUT_SPEAKER:
+ case SND_DEVICE_OUT_SPEAKER_SAFE:
+ case SND_DEVICE_OUT_SPEAKER_REVERSE:
+ case SND_DEVICE_OUT_SPEAKER_PROTECTED:
+ case SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED:
+ case SND_DEVICE_OUT_VOICE_SPEAKER_HFP:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
diff --git a/hal/platform_api.h b/hal/platform_api.h
index e7c26e7..be1c653 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -104,6 +104,8 @@
int platform_set_snd_device_backend(snd_device_t snd_device, const char * backend,
const char * hw_interface);
+bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id);
+
/* From platform_info.c */
int platform_info_init(const char *filename, void *);
@@ -148,4 +150,6 @@
bool enable, char * str);
int platform_get_mmap_data_fd(void *platform, int dev, int dir,
int *fd, uint32_t *size);
+bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id);
+bool platform_snd_device_has_speaker(snd_device_t dev);
#endif // AUDIO_PLATFORM_API_H