diff options
| author | JJ Lee <leejj@google.com> | 2019-05-17 17:34:37 -0700 |
|---|---|---|
| committer | JJ Lee <leejj@google.com> | 2019-05-30 09:12:43 -0700 |
| commit | dab49845f6714092b00bcb08ed55886ad65baba7 (patch) | |
| tree | 3e1467c0836e1aef2bd49a0417e799bf156d0c08 | |
| parent | 843495c5e1c2cfa35a94a5e17706e338bfa1241e (diff) | |
| download | android_hardware_knowles_athletico_sound_trigger_hal-dab49845f6714092b00bcb08ed55886ad65baba7.tar.gz android_hardware_knowles_athletico_sound_trigger_hal-dab49845f6714092b00bcb08ed55886ad65baba7.tar.bz2 android_hardware_knowles_athletico_sound_trigger_hal-dab49845f6714092b00bcb08ed55886ad65baba7.zip | |
sthal: Destroy Oslo plugin asynchronously
+ Inform the Host 1 that Host 0 is about to teardown Oslo routes and
packages.
Wait for the OSLO_EP_DISCONNECT event from the Host 1, once the event
has been received, teardown the route and destroy the packages.
+ To ensure that sensor create doesn't happen before the previous sensor
destroy is completed, have a wait condition for the previous sensor
destroy to finish. Wait for a max 5 seconds, if by then the destroy is
not completed then go ahead and destroy it and then create it.
The wait is done in chunks of 1 second to ensure that we check if the
destroy has happened asynchronously, either by timer expiry or by
receipt of the event.
+ Also create a timer of 5 seconds, if Host 1 doesn't respond within 5
seconds, then force destroy the OSLO plugins
+ During crash recovery, there is nothing to destroy, so send a signal
to any waiting threads and delete the timer if it has been created.
Test: Oslo on/off test, can recover after crash
Bug:132633987
Change-Id: I273183f07f58ecee6931f6cba9dc90cfe1c58889
Signed-off-by: JJ Lee <leejj@google.com>
| -rw-r--r-- | cvq_ioctl.h | 2 | ||||
| -rw-r--r-- | cvq_util.c | 39 | ||||
| -rw-r--r-- | sound_trigger_hw_iaxxx.c | 297 |
3 files changed, 298 insertions, 40 deletions
diff --git a/cvq_ioctl.h b/cvq_ioctl.h index 22b501a..272bae2 100644 --- a/cvq_ioctl.h +++ b/cvq_ioctl.h @@ -56,6 +56,7 @@ #define SENSOR_MAX_MODE 2 #define OSLO_CONFIGURED (0x201) #define OSLO_DESTROYED (0x202) +#define OSLO_EP_DISCONNECT (0x205) #define OSLO_BUF_INSTANCE_ID 8 #define AEC_PKG_ID 7 @@ -204,4 +205,5 @@ int power_off_proc_mem_in_retn(struct audio_route *route_hdl, int enable, int co int power_on_proc_mem_out_off_retn(struct audio_route *route_hdl, int enable, int core); int get_fw_status(struct iaxxx_odsp_hw *odsp_hdl, unsigned int *status); int reset_fw(struct iaxxx_odsp_hw *odsp_hdl); +int trigger_sensor_destroy_event(struct iaxxx_odsp_hw *odsp_hdl); #endif /* _CVQ_IOCTL_H */ @@ -510,6 +510,14 @@ int sensor_event_init_params(struct iaxxx_odsp_hw *odsp_hdl) goto exit; } + err = iaxxx_odsp_evt_subscribe(odsp_hdl, IAXXX_SYSID_HOST_1, + OSLO_EP_DISCONNECT, IAXXX_SYSID_HOST_0, 0); + if (err == -1) { + ALOGE("%s: ERROR: oslo event subscription (oslo ep disconnect) failed with" + " error %d(%s)", __func__, errno, strerror(errno)); + goto exit; + } + err = iaxxx_odsp_evt_trigger(odsp_hdl, OSLO_EVT_SRC_ID, OSLO_CONFIGURED, 0); if (err != 0) { ALOGE("%s: ERROR: olso event trigger (oslo configured) failed %d(%s)", @@ -529,13 +537,6 @@ static int sensor_event_deinit_params(struct iaxxx_odsp_hw *odsp_hdl) ALOGD("+%s+", __func__); - err = iaxxx_odsp_evt_trigger(odsp_hdl, OSLO_EVT_SRC_ID, OSLO_DESTROYED, 0); - if (err != 0) { - ALOGE("%s: ERROR: Oslo event trigger (oslo destroyed) failed %d(%s)", - __func__, errno, strerror(errno)); - goto exit; - } - err = iaxxx_odsp_evt_unsubscribe(odsp_hdl, OSLO_EVT_SRC_ID, SENSOR_MAX_MODE, IAXXX_SYSID_HOST); if (err != 0) { @@ -581,6 +582,15 @@ static int sensor_event_deinit_params(struct iaxxx_odsp_hw *odsp_hdl) goto exit; } + err = iaxxx_odsp_evt_unsubscribe(odsp_hdl, IAXXX_SYSID_HOST_1, + OSLO_EP_DISCONNECT, IAXXX_SYSID_HOST_0); + if (err != 0) { + ALOGE("%s: Failed to unsubscribe sensor event (src id %d event id %d)" + " from host %d with the error %d(%s)", __func__, IAXXX_SYSID_HOST_1, + OSLO_EP_DISCONNECT, IAXXX_SYSID_HOST_0, errno, strerror(errno)); + goto exit; + } + ALOGD("-%s-", __func__); exit: @@ -1125,6 +1135,21 @@ exit: return err; } +int trigger_sensor_destroy_event(struct iaxxx_odsp_hw *odsp_hdl) +{ + int err = 0; + + ALOGD("+%s+", __func__); + + err = iaxxx_odsp_evt_trigger(odsp_hdl, OSLO_EVT_SRC_ID, OSLO_DESTROYED, 0); + if (err == -1) + ALOGE("%s: ERROR: oslo event trigger (oslo destroyed) failed with " + "error %d(%s)", __func__, errno, strerror(errno)); + + ALOGD("-%s-", __func__); + return err; +} + int setup_mixer_package(struct iaxxx_odsp_hw *odsp_hdl) { int err = 0; diff --git a/sound_trigger_hw_iaxxx.c b/sound_trigger_hw_iaxxx.c index 2c7f23c..25a7ab1 100644 --- a/sound_trigger_hw_iaxxx.c +++ b/sound_trigger_hw_iaxxx.c @@ -73,6 +73,9 @@ #define RETRY_NUMBER (10) #define RETRY_US (500000) +#define SENSOR_CREATE_WAIT_TIME_IN_S (1) +#define SENSOR_CREATE_WAIT_MAX_COUNT (5) + #ifdef __LP64__ #define ADNC_STRM_LIBRARY_PATH "/vendor/lib64/hw/adnc_strm.primary.default.so" #else @@ -121,6 +124,7 @@ struct knowles_sound_trigger_device { sound_trigger_uuid_t authkw_model_uuid; pthread_t callback_thread; pthread_mutex_t lock; + pthread_cond_t sensor_create; int opened; int send_sock; int recv_sock; @@ -146,6 +150,7 @@ struct knowles_sound_trigger_device { bool is_music_playing; bool is_bargein_route_enabled; bool is_buffer_package_loaded; + bool is_sensor_route_enabled; bool is_st_hal_ready; bool is_hmd_proc_on; bool is_dmx_proc_on; @@ -153,6 +158,7 @@ struct knowles_sound_trigger_device { int music_buffer_enable; bool is_chre_enable; bool is_media_recording; + bool is_sensor_destroy_in_prog; unsigned int current_enable; @@ -167,14 +173,21 @@ struct knowles_sound_trigger_device { int snd_crd_num; char mixer_path_xml[NAME_MAX_SIZE]; bool fw_reset_done_by_hal; + + // sensor stop signal event + timer_t ss_timer; + bool ss_timer_created; }; /* * Since there's only ever one sound_trigger_device, keep it as a global so * that other people can dlopen this lib to get at the streaming audio. */ -static struct knowles_sound_trigger_device g_stdev = { - .lock = PTHREAD_MUTEX_INITIALIZER + +static struct knowles_sound_trigger_device g_stdev = +{ + .lock = PTHREAD_MUTEX_INITIALIZER, + .sensor_create = PTHREAD_COND_INITIALIZER }; static bool check_uuid_equality(sound_trigger_uuid_t uuid1, @@ -951,21 +964,38 @@ static int restart_recognition(struct knowles_sound_trigger_device *stdev) if (stdev->models[i].is_loaded == true) { if (check_uuid_equality(stdev->models[i].uuid, stdev->sensor_model_uuid)) { - // setup the sensor route - err = setup_sensor_package(stdev->odsp_hdl); - if (err != 0) { - ALOGE("%s: setup Sensor package failed", __func__); - goto exit; - } err = set_sensor_route(stdev->route_hdl, false); if (err != 0) { ALOGE("%s: tear Sensor route fail", __func__); goto exit; } - err = set_sensor_route(stdev->route_hdl, true); - if (err != 0) { - ALOGE("%s: Sensor route fail", __func__); - goto exit; + stdev->is_sensor_route_enabled = false; + + if (stdev->is_sensor_destroy_in_prog == true) { + stdev->is_sensor_destroy_in_prog = false; + pthread_cond_signal(&stdev->sensor_create); + + // A timer would have been created during stop, + // check and delete it, as there is nothing to destroy + // at this point + if (stdev->ss_timer_created) { + timer_delete(stdev->ss_timer); + stdev->ss_timer_created = false; + } + } else { + // setup the sensor route + err = setup_sensor_package(stdev->odsp_hdl); + if (err != 0) { + ALOGE("%s: setup Sensor package failed", __func__); + goto exit; + } + + err = set_sensor_route(stdev->route_hdl, true); + if (err != 0) { + ALOGE("%s: Sensor route fail", __func__); + goto exit; + } + stdev->is_sensor_route_enabled = true; } } } @@ -997,6 +1027,155 @@ exit: return err; } +static void check_and_turn_off_hmd(struct knowles_sound_trigger_device *stdev) +{ + ALOGD("+%s+", __func__); + + // Switch the processor off only if all packages are unloaded + if (!is_any_model_loaded(stdev) && stdev->is_hmd_proc_on) { + power_on_proc_mem(stdev->route_hdl, false, IAXXX_HMD_ID); + stdev->is_hmd_proc_on = false; + } + + ALOGD("-%s-", __func__); +} + +static void remove_buffer(struct knowles_sound_trigger_device *stdev) +{ + ALOGD("+%s+", __func__); + + if (!is_any_model_loaded(stdev) && + stdev->is_buffer_package_loaded && + !stdev->is_sensor_destroy_in_prog && + !stdev->is_sensor_route_enabled) { + destroy_buffer_package(stdev->odsp_hdl); + stdev->is_buffer_package_loaded = false; + } + + ALOGD("-%s-", __func__); +} + +static void destroy_sensor_model(struct knowles_sound_trigger_device *stdev) +{ + int ret, i; + ALOGD("+%s+", __func__); + + if (stdev->is_sensor_route_enabled == true) { + ret = set_sensor_route(stdev->route_hdl, false); + if (ret != 0) { + ALOGE("%s: tear Sensor route fail", __func__); + } + stdev->is_sensor_route_enabled = false; + + ret = destroy_sensor_package(stdev->odsp_hdl); + if (ret != 0) { + ALOGE("%s: destroy Sensor package failed %d", + __func__, ret); + } + stdev->current_enable = stdev->current_enable & ~OSLO_MASK; + } + + // now we can change the flag + for (i = 0 ; i < MAX_MODELS ; i++) { + if (check_uuid_equality(stdev->models[i].uuid, + stdev->sensor_model_uuid)) { + stdev->models[i].is_loaded = false; + break; + } + } + + stdev->is_sensor_destroy_in_prog = false; + remove_buffer(stdev); + check_and_turn_off_hmd(stdev); + + // There could be another thread waiting for us to destroy so signal that + // thread, if no one is waiting then this signal will have no effect + pthread_cond_signal(&stdev->sensor_create); + + ALOGD("-%s-", __func__); +} + +static void sensor_stop_timeout() +{ + ALOGD("+%s+", __func__); + + struct knowles_sound_trigger_device *stdev = &g_stdev; + pthread_mutex_lock(&stdev->lock); + // We are here because we timed out so check if we still need to destroy + // the sensor package, if yes then go ahead otherwise do nothing + if (stdev->is_sensor_destroy_in_prog == true) { + destroy_sensor_model(stdev); + } + pthread_mutex_unlock(&stdev->lock); + ALOGD("-%s-", __func__); +} + +static int start_sensor_model(struct knowles_sound_trigger_device * stdev) +{ + struct timespec ts; + int wait_counter = 0, err = 0; + + while (stdev->is_sensor_destroy_in_prog == true && + wait_counter < SENSOR_CREATE_WAIT_MAX_COUNT) { + // We wait for 1sec * MAX_COUNT times for the HOST 1 to respond, if + // within that time we don't get any response, we will go ahead with the + // sensor model creation. Note this might result in an error which would + // be better than blocking the thread indefinitely. + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += SENSOR_CREATE_WAIT_TIME_IN_S; + err = pthread_cond_timedwait(&stdev->sensor_create, &stdev->lock, &ts); + if (err == ETIMEDOUT) { + ALOGE("%s: WARNING: Sensor create timed out after %ds", + __func__, SENSOR_CREATE_WAIT_TIME_IN_S); + wait_counter++; + } + } + + // Reset timedout error + err = 0; + + if (stdev->is_sensor_destroy_in_prog == true) { + ALOGE("%s: ERROR: Waited for %ds but we didn't get the event from " + "Host 1, forcing a destroy", __func__, + SENSOR_CREATE_WAIT_TIME_IN_S * SENSOR_CREATE_WAIT_MAX_COUNT); + stdev->is_sensor_destroy_in_prog = false; + + if (stdev->is_sensor_route_enabled == true) { + err = set_sensor_route(stdev->route_hdl, false); + if (err) { + ALOGE("%s: Failed to tear sensor route", __func__); + goto exit; + } + err = destroy_sensor_package(stdev->odsp_hdl); + if (err) { + ALOGE("%s: ERROR: Failed to destroy sensor package", __func__); + goto exit; + } + stdev->is_sensor_route_enabled = false; + } + } + + if(stdev->is_sensor_route_enabled == false) { + err = setup_sensor_package(stdev->odsp_hdl); + if (err) { + ALOGE("%s: Failed to setup sensor package", __func__); + goto exit; + } + // Don't download the keyword model file, just setup the + // sensor route + err = set_sensor_route(stdev->route_hdl, true); + if (err) { + ALOGE("%s: Sensor route fail", __func__); + goto exit; + } + stdev->is_sensor_route_enabled = true; + stdev->current_enable = stdev->current_enable | OSLO_MASK; + } + +exit: + return err; +} + static void *callback_thread_loop(void *context) { struct knowles_sound_trigger_device *stdev = @@ -1116,6 +1295,24 @@ static void *callback_thread_loop(void *context) AMBIENT_KW_ID); kwid = AMBIENT_KW_ID; reset_ambient_plugin(stdev->odsp_hdl); + } else if (ge.event_id == OSLO_EP_DISCONNECT) { + ALOGD("Eventid received is OSLO_EP_DISCONNECT %d", + OSLO_EP_DISCONNECT); + if (stdev->is_sensor_destroy_in_prog == true) { + destroy_sensor_model(stdev); + + // A timer would have been created during stop, + // check and delete it + if (stdev->ss_timer_created) { + timer_delete(stdev->ss_timer); + stdev->ss_timer_created = false; + } + } else { + ALOGE("Unexpected OSLO_EP_DISCONNECT received" + ", ignoring.."); + } + + break; } else if (ge.event_id == ENTITY_KW_ID) { ALOGD("Eventid received is ENTITY_KW_ID %d", ENTITY_KW_ID); @@ -1468,16 +1665,9 @@ static int stdev_load_sound_model(const struct sound_trigger_hw_device *dev, } else if (check_uuid_equality(stdev->models[i].uuid, stdev->sensor_model_uuid)) { // setup the sensor route - stdev->current_enable = stdev->current_enable | OSLO_MASK; - ret = setup_sensor_package(stdev->odsp_hdl); - if (ret != 0) { - ALOGE("%s: setup Sensor package failed", __func__); - goto exit; - } - - ret = set_sensor_route(stdev->route_hdl, true); - if (ret != 0) { - ALOGE("%s: Sensor route fail", __func__); + ret = start_sensor_model(stdev); + if (ret) { + ALOGE("%s: ERROR: Failed to start sensor model", __func__); goto exit; } stdev->models[i].kw_id = USELESS_KW_ID; @@ -1556,20 +1746,47 @@ static int stdev_unload_sound_model(const struct sound_trigger_hw_device *dev, goto exit; } - if (check_uuid_equality(stdev->models[handle].uuid, stdev->sensor_model_uuid)) { - // Disable the sensor route - ret = set_sensor_route(stdev->route_hdl, false); - if (ret != 0) { - ALOGE("%s: disable Sensor route failed", __func__); - } + // Inform the Host 1 that sensor route/packages are about to be + // torndown and then wait for confirmation from Host 1 that it can be + // torndown. Also start a timer for 5 seconds, if the Host 1 doesn't + // send us the event within 5 seconds we force remove the sensor pkgs + if (stdev->is_sensor_route_enabled == true) { + struct itimerspec ss_timer_spec; + struct sigevent ss_sigevent; + + // Inform the host 1 + stdev->is_sensor_destroy_in_prog = true; + trigger_sensor_destroy_event(stdev->odsp_hdl); + + // Start timer for 5 seconds + ss_sigevent.sigev_notify = SIGEV_THREAD; + ss_sigevent.sigev_notify_function = sensor_stop_timeout; + ss_sigevent.sigev_notify_attributes = NULL; + + ss_timer_spec.it_interval.tv_sec = 0; + ss_timer_spec.it_interval.tv_nsec = 0; + ss_timer_spec.it_value.tv_sec = + SENSOR_CREATE_WAIT_TIME_IN_S * SENSOR_CREATE_WAIT_MAX_COUNT; + ss_timer_spec.it_value.tv_nsec = 0; + + if (stdev->ss_timer_created) { + timer_delete(stdev->ss_timer); + stdev->ss_timer_created = false; + } - ret = destroy_sensor_package(stdev->odsp_hdl); - if (ret != 0) { - ALOGE("%s: destroy Sensor package failed", __func__); + if (timer_create(CLOCK_REALTIME, + &ss_sigevent, &stdev->ss_timer) == -1) { + ALOGE("%s: Timer Create Failed", __func__); + } else { + stdev->ss_timer_created = true; + if (timer_settime(stdev->ss_timer, + 0, &ss_timer_spec, NULL) == -1) { + ALOGE("%s: Timer Set Failed", __func__); + } + } } - stdev->current_enable = stdev->current_enable & ~OSLO_MASK; } else if (check_uuid_equality(stdev->models[handle].uuid, stdev->chre_model_uuid)) { if (stdev->models[handle].is_active == true) { @@ -1584,7 +1801,12 @@ static int stdev_unload_sound_model(const struct sound_trigger_hw_device *dev, stdev->models[handle].sound_model_callback = NULL; stdev->models[handle].sound_model_cookie = NULL; - stdev->models[handle].is_loaded = false; + + if (!(check_uuid_equality(stdev->models[handle].uuid, + stdev->sensor_model_uuid) && + stdev->is_sensor_destroy_in_prog)) + stdev->models[handle].is_loaded = false; + if (stdev->models[handle].data) { free(stdev->models[handle].data); stdev->models[handle].data = NULL; @@ -1845,6 +2067,11 @@ static int stdev_close(hw_device_t *device) if (stdev->odsp_hdl) iaxxx_odsp_deinit(stdev->odsp_hdl); + if (stdev->ss_timer_created) { + timer_delete(stdev->ss_timer); + stdev->ss_timer_created = false; + } + exit: pthread_mutex_unlock(&stdev->lock); ALOGD("-%s-", __func__); @@ -2139,11 +2366,15 @@ static int stdev_open(const hw_module_t *module, const char *name, stdev->hotword_buffer_enable = 0; stdev->music_buffer_enable = 0; stdev->current_enable = 0; + stdev->is_sensor_route_enabled = false; stdev->is_hmd_proc_on = false; stdev->is_dmx_proc_on = false; stdev->is_chre_enable = false; stdev->is_media_recording = false; + stdev->is_sensor_destroy_in_prog = false; + stdev->ss_timer_created = false; + stdev->snd_crd_num = snd_card_num; stdev->fw_reset_done_by_hal = false; |
