diff options
author | Xin Li <delphij@google.com> | 2020-09-08 16:55:29 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2020-09-08 16:55:29 -0700 |
commit | 373609b1193ba3609bd985d83d4db13a2d1aecdc (patch) | |
tree | e4f796af2471b45db3b3b1a58cb093c6bba05159 | |
parent | 8a6f081643f8abf7643a87077ea6008067b280c9 (diff) | |
parent | bc0652dfdba66101d9cbd2294fac6a1309257b4c (diff) | |
download | sound_trigger_hal-373609b1193ba3609bd985d83d4db13a2d1aecdc.tar.gz |
Merge Android R
Bug: 168057903
Merged-In: I941272023ad401c3b4d5e4bfa17a0e6080331cf7
Change-Id: I1021925164a8e1d6886a1b0acd12d44ea08b5638
-rw-r--r-- | cvq_ioctl.h | 6 | ||||
-rw-r--r-- | cvq_util.c | 89 | ||||
-rw-r--r-- | sound_trigger_hw_iaxxx.c | 666 | ||||
-rw-r--r-- | sound_trigger_intf.h | 13 | ||||
-rw-r--r-- | tests/oslo_config_test.c | 10 | ||||
-rw-r--r-- | tests/oslo_iaxxx_sensor_control.h | 10 |
6 files changed, 511 insertions, 283 deletions
diff --git a/cvq_ioctl.h b/cvq_ioctl.h index c212e42..232e928 100644 --- a/cvq_ioctl.h +++ b/cvq_ioctl.h @@ -111,6 +111,10 @@ #define AMBIENT_UNLOAD_PARAM_ID 1 #define AMBIENT_RESET_PARAM_ID 2 #define AMBIENT_GET_MODEL_STATE_PARAM_ID 7 +#define HOTWORD_GET_VERSION_PARAM_ID 8 +#define AMBIENT_GET_VERSION_PARAM_ID 8 +#define HOTWORD_DEFAULT_VER 0 +#define AMBIENT_DEFAULT_VER 0 #define BUFFER_PACKAGE "BufferPackage.bin" #define BUFFER_CONFIG_OSLO_VAL "BufferConfigValOslo.bin" @@ -198,8 +202,10 @@ int setup_buffer_package(struct iaxxx_odsp_hw *odsp_hdl); int destroy_buffer_package(struct iaxxx_odsp_hw *odsp_hdl); int setup_hotword_package(struct iaxxx_odsp_hw *odsp_hdl); int destroy_hotword_package(struct iaxxx_odsp_hw *odsp_hdl); +unsigned int get_hotword_version(struct iaxxx_odsp_hw *odsp_hdl); int setup_ambient_package(struct iaxxx_odsp_hw *odsp_hdl); int destroy_ambient_package(struct iaxxx_odsp_hw *odsp_hdl); +unsigned int get_ambient_version(struct iaxxx_odsp_hw *odsp_hdl); int setup_aec_package(struct iaxxx_odsp_hw *odsp_hdl); int destroy_aec_package(struct iaxxx_odsp_hw *odsp_hdl); int setup_chre_package(struct iaxxx_odsp_hw *odsp_hdl); @@ -796,6 +796,48 @@ exit: return err; } +unsigned int get_hotword_version(struct iaxxx_odsp_hw *odsp_hdl) +{ + int err = 0; + const uint32_t inst_id = HOTWORD_INSTANCE_ID; + const uint32_t param_id = HOTWORD_GET_VERSION_PARAM_ID; + const uint32_t block_id = IAXXX_HMD_BLOCK_ID; + unsigned int param_val = HOTWORD_DEFAULT_VER; + + err = setup_hotword_package(odsp_hdl); + if (err != 0) { + if (errno == EEXIST) { + ALOGW("%s: WARN: Hotword package existed already", __func__); + err = iaxxx_odsp_plugin_get_parameter(odsp_hdl, inst_id, param_id, + block_id, ¶m_val); + if (err != 0) { + ALOGE("%s: Failed to get parameter for id %u with error %d: %s", + __func__, param_id, err, strerror(errno)); + } else { + ALOGD("%s: Value of parameter id %u is %u", __func__, param_id, + param_val); + } + } else { + ALOGE("%s: ERROR: setup hotword package failed", __func__); + } + } else { + err = iaxxx_odsp_plugin_get_parameter(odsp_hdl, inst_id, param_id, + block_id, ¶m_val); + if (err != 0) { + ALOGE("%s: Failed to get parameter for id %u with error %d: %s", + __func__, param_id, err, strerror(errno)); + } else { + ALOGD("%s: Value of parameter id %u is %u", __func__, param_id, + param_val); + } + err = destroy_hotword_package(odsp_hdl); + if (err != 0) + ALOGE("%s: ERROR: destroy hotword package failed", __func__); + } + + return param_val; +} + int setup_ambient_package(struct iaxxx_odsp_hw *odsp_hdl) { int err = 0; @@ -863,6 +905,48 @@ exit: return err; } +unsigned int get_ambient_version(struct iaxxx_odsp_hw *odsp_hdl) +{ + int err = 0; + const uint32_t inst_id = AMBIENT_INSTANCE_ID; + const uint32_t param_id = AMBIENT_GET_VERSION_PARAM_ID; + const uint32_t block_id = IAXXX_HMD_BLOCK_ID; + unsigned int param_val = AMBIENT_DEFAULT_VER; + + err = setup_ambient_package(odsp_hdl); + if (err != 0) { + if (errno == EEXIST) { + ALOGW("%s: WARN: Ambient package existed already", __func__); + err = iaxxx_odsp_plugin_get_parameter(odsp_hdl, inst_id, param_id, + block_id, ¶m_val); + if (err != 0) { + ALOGE("%s: Failed to get parameter for id %u with error %d: %s", + __func__, param_id, err, strerror(errno)); + } else { + ALOGD("%s: Value of parameter id %u is %u", __func__, param_id, + param_val); + } + } else { + ALOGE("%s: ERROR: setup Ambient package failed", __func__); + } + } else { + err = iaxxx_odsp_plugin_get_parameter(odsp_hdl, inst_id, param_id, + block_id, ¶m_val); + if (err != 0) { + ALOGE("%s: Failed to get parameter for id %u with error %d: %s", + __func__, param_id, err, strerror(errno)); + } else { + ALOGD("%s: Value of parameter id %u is %u", __func__, param_id, + param_val); + } + err = destroy_ambient_package(odsp_hdl); + if (err != 0) + ALOGE("%s: ERROR: destroy Ambient package failed", __func__); + } + + return param_val; +} + int setup_aec_package(struct iaxxx_odsp_hw *odsp_hdl) { int err = 0; @@ -1796,10 +1880,7 @@ int reset_all_route(struct audio_route *route_hdl) ALOGD("+%s+", __func__); for (int i = ST_ROUTE_MIN; i < ST_ROUTE_MAX; i++) { - /*[TODO] Need to use force_reset to clean the active count - * inside libaudioroute - */ - audio_route_reset_and_update_path(route_hdl, route_table[i]); + audio_route_force_reset_and_update_path(route_hdl, route_table[i]); } ALOGD("-%s-", __func__); return err; diff --git a/sound_trigger_hw_iaxxx.c b/sound_trigger_hw_iaxxx.c index e7a3556..014c96a 100644 --- a/sound_trigger_hw_iaxxx.c +++ b/sound_trigger_hw_iaxxx.c @@ -73,8 +73,8 @@ #define SOUND_TRIGGER_MIXER_PATH_XML "/vendor/etc/sound_trigger_mixer_paths_default.xml" #define MAX_SND_CARD (8) -#define RETRY_NUMBER (10) -#define RETRY_US (500000) +#define RETRY_NUMBER (40) +#define RETRY_US (1000000) #define TUNNEL_TIMEOUT 5 #define SENSOR_CREATE_WAIT_TIME_IN_S (1) @@ -83,6 +83,8 @@ #define CHRE_CREATE_WAIT_TIME_IN_S (1) #define CHRE_CREATE_WAIT_MAX_COUNT (5) +#define FIRMWARE_READY_WAIT_TIME_IN_S (4) + #define ST_DEVICE_HANDSET_MIC 1 #ifdef __LP64__ @@ -91,22 +93,30 @@ #define ADNC_STRM_LIBRARY_PATH "/vendor/lib/hw/adnc_strm.primary.default.so" #endif -static const struct sound_trigger_properties hw_properties = { - "Knowles Electronics", // implementor - "Continous VoiceQ", // description - 1, // version - // Version UUID - { 0x80f7dcd5, 0xbb62, 0x4816, 0xa931, {0x9c, 0xaa, 0x52, 0x5d, 0xf5, 0xc7}}, - MAX_MODELS, // max_sound_models - MAX_KEY_PHRASES, // max_key_phrases - MAX_USERS, // max_users - RECOGNITION_MODE_VOICE_TRIGGER | // recognition_mode - RECOGNITION_MODE_GENERIC_TRIGGER, - true, // capture_transition - MAX_BUFFER_MS, // max_capture_ms - true, // concurrent_capture - false, // trigger_in_event - POWER_CONSUMPTION // power_consumption_mw +static struct sound_trigger_properties_extended_1_3 hw_properties = { + { + SOUND_TRIGGER_DEVICE_API_VERSION_1_3, //ST version + sizeof(struct sound_trigger_properties_extended_1_3) + }, + { + "Knowles Electronics", // implementor + "Continuous VoiceQ", // description + 0, // library version + // Version UUID + { 0x80f7dcd5, 0xbb62, 0x4816, 0xa931, {0x9c, 0xaa, 0x52, 0x5d, 0xf5, 0xc7}}, + MAX_MODELS, // max_sound_models + MAX_KEY_PHRASES, // max_key_phrases + MAX_USERS, // max_users + RECOGNITION_MODE_VOICE_TRIGGER | // recognition_mode + RECOGNITION_MODE_GENERIC_TRIGGER, + true, // capture_transition + MAX_BUFFER_MS, // max_capture_ms + true, // concurrent_capture + false, // trigger_in_event + POWER_CONSUMPTION // power_consumption_mw + }, + "9b55e25e-8ea3-4f73-bce9-b37860d57f5a", //supported arch + 0, // audio capability }; struct model_info { @@ -139,10 +149,10 @@ struct knowles_sound_trigger_device { pthread_cond_t tunnel_create; pthread_cond_t sensor_create; pthread_cond_t chre_create; + pthread_cond_t firmware_ready_cond; int opened; int send_sock; int recv_sock; - struct sound_trigger_recognition_config *last_keyword_detected_config; // Information about streaming int is_streaming; @@ -160,7 +170,6 @@ struct knowles_sound_trigger_device { sound_trigger_uuid_t entity_model_uuid; sound_trigger_uuid_t wakeup_model_uuid; - int last_detected_model_type; bool is_mic_route_enabled; bool is_bargein_route_enabled; bool is_chre_loaded; @@ -205,6 +214,7 @@ struct knowles_sound_trigger_device { // Chre stop signal event timer_t chre_timer; bool chre_timer_created; + unsigned int hotword_version; }; /* @@ -215,9 +225,11 @@ struct knowles_sound_trigger_device { static struct knowles_sound_trigger_device g_stdev = { .lock = PTHREAD_MUTEX_INITIALIZER, + .transition_cond = PTHREAD_COND_INITIALIZER, .tunnel_create = PTHREAD_COND_INITIALIZER, .sensor_create = PTHREAD_COND_INITIALIZER, - .chre_create = PTHREAD_COND_INITIALIZER + .chre_create = PTHREAD_COND_INITIALIZER, + .firmware_ready_cond = PTHREAD_COND_INITIALIZER }; static struct timespec reset_time = {0}; @@ -524,7 +536,6 @@ static char *stdev_generic_event_alloc(int model_handle, void *payload, event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT; if (payload && payload_size > 0) { - ALOGD("%s: Attach payload in the event", __func__); event->common.data_size = payload_size; event->common.data_offset = sizeof(struct sound_trigger_generic_recognition_event); @@ -598,6 +609,28 @@ static void update_recover_list(struct knowles_sound_trigger_device *stdev, return; } +int check_firmware_ready(struct knowles_sound_trigger_device *stdev) +{ + int err = 0; + + if (stdev->is_st_hal_ready == false) { + struct timespec ts; + ALOGW("%s: ST HAL is not ready yet", __func__); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += FIRMWARE_READY_WAIT_TIME_IN_S; + err = pthread_cond_timedwait(&stdev->firmware_ready_cond, + &stdev->lock, &ts); + if (err == ETIMEDOUT) { + ALOGE("%s: WARNING: firmware downloading timed out after %ds", + __func__, FIRMWARE_READY_WAIT_TIME_IN_S); + err = -ENODEV; + } else if (err != 0) + err = -EINVAL; + } + + return err; +} + static int check_and_setup_src_package( struct knowles_sound_trigger_device *stdev) { @@ -605,18 +638,11 @@ static int check_and_setup_src_package( if (stdev->is_src_package_loaded == false) { err = setup_src_package(stdev->odsp_hdl); - if (err != 0) { - ALOGE("%s: Failed to load SRC package", __func__); - goto exit; - } else { - ALOGD("%s: SRC package loaded", __func__); - stdev->is_src_package_loaded = true; - } + stdev->is_src_package_loaded = true; } else { ALOGD("%s: SRC package is already loaded", __func__); } -exit: return err; } @@ -627,16 +653,11 @@ static int check_and_destroy_src_package( if (!is_any_model_active(stdev) && stdev->is_src_package_loaded == true) { err = destroy_src_package(stdev->odsp_hdl); - if (err != 0) { - ALOGE("%s: Failed to destroy SRC package", __func__); - goto exit; - } else { - ALOGD("%s: SRC package destroy", __func__); - stdev->is_src_package_loaded = false; - } + stdev->is_src_package_loaded = false; + } else { + ALOGD("%s: Can't destroy package due to active status", __func__); } -exit: return err; } @@ -647,18 +668,11 @@ static int check_and_setup_buffer_package( if (stdev->is_buffer_package_loaded == false) { err = setup_buffer_package(stdev->odsp_hdl); - if (err != 0) { - ALOGE("%s: Failed to load Buffer package", __func__); - goto exit; - } else { - ALOGD("%s: Buffer package loaded", __func__); - stdev->is_buffer_package_loaded = true; - } + stdev->is_buffer_package_loaded = true; } else { ALOGD("%s: Buffer package is already loaded", __func__); } -exit: return err; } @@ -675,16 +689,11 @@ static int check_and_destroy_buffer_package( !stdev->is_chre_loaded)) { err = destroy_buffer_package(stdev->odsp_hdl); - if (err != 0) { - ALOGE("%s: Failed to destroy Buffer package", __func__); - goto exit; - } else { - ALOGD("%s: Buffer package destroy", __func__); - stdev->is_buffer_package_loaded = false; - } + stdev->is_buffer_package_loaded = false; + } else { + ALOGD("%s: Can't destroy package due to active status", __func__); } -exit: return err; } @@ -698,7 +707,6 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, err = setup_chre_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to load CHRE package"); - goto exit; } } stdev->current_enable = stdev->current_enable | CHRE_MASK; @@ -707,14 +715,12 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, err = setup_hotword_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to load Hotword package"); - goto exit; } } err = write_model(stdev->odsp_hdl, model->data, model->data_sz, model->kw_id); if (err != 0) { ALOGE("Failed to write Hotword model"); - goto exit; } //setup model state. @@ -722,21 +728,18 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, err = set_hotword_state(stdev->odsp_hdl, stdev->current_enable); if (err != 0) { ALOGE("Failed to set Hotword state"); - goto exit; } } else if (check_uuid_equality(model->uuid, stdev->wakeup_model_uuid)) { if (!(stdev->current_enable & PLUGIN1_MASK)) { err = setup_hotword_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to load Hotword package"); - goto exit; } } err = write_model(stdev->odsp_hdl, model->data, model->data_sz, model->kw_id); if (err != 0) { ALOGE("Failed to write Wakeup model"); - goto exit; } //setup model state. @@ -744,14 +747,12 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, err = set_hotword_state(stdev->odsp_hdl, stdev->current_enable); if (err != 0) { ALOGE("Failed to set Wakeup state"); - goto exit; } } else if (check_uuid_equality(model->uuid, stdev->ambient_model_uuid)) { if (!(stdev->current_enable & PLUGIN2_MASK)) { err = setup_ambient_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to load Ambient package"); - goto exit; } } else { // tear down plugin2 for writing new model data. @@ -762,7 +763,6 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, model->data_sz, model->kw_id); if (err != 0) { ALOGE("Failed to write Ambient model"); - goto exit; } //setup model state. @@ -770,7 +770,6 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, err = set_ambient_state(stdev->odsp_hdl, stdev->current_enable); if (err != 0) { ALOGE("Failed to set Ambient state"); - goto exit; } } else if (check_uuid_equality(model->uuid, stdev->entity_model_uuid)) { @@ -778,7 +777,6 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, err = setup_ambient_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to load Ambient package"); - goto exit; } } else { // tear down plugin2 for writing new model data. @@ -789,7 +787,6 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, model->data_sz, model->kw_id); if (err != 0) { ALOGE("Failed to write Entity model"); - goto exit; } //setup model state. @@ -797,11 +794,9 @@ static int setup_package(struct knowles_sound_trigger_device *stdev, err = set_ambient_state(stdev->odsp_hdl, stdev->current_enable); if (err != 0) { ALOGE("Failed to set Entity state"); - goto exit; } } -exit: return err; } @@ -815,27 +810,29 @@ static int setup_buffer(struct knowles_sound_trigger_device *stdev, || (check_uuid_equality(model->uuid, stdev->wakeup_model_uuid))) { stdev->hotword_buffer_enable++; - if (stdev->hotword_buffer_enable > 1) + if (stdev->hotword_buffer_enable > 1) { + ALOGD("%d models are using hotword buffer", + stdev->hotword_buffer_enable); goto exit; - + } err = setup_howord_buffer(stdev->odsp_hdl); if (err != 0) { stdev->hotword_buffer_enable--; ALOGE("Failed to create the buffer plugin"); - goto exit; } } else if ((check_uuid_equality(model->uuid, stdev->ambient_model_uuid)) || (check_uuid_equality(model->uuid, stdev->entity_model_uuid))) { stdev->music_buffer_enable++; - if (stdev->music_buffer_enable > 1) + if (stdev->music_buffer_enable > 1) { + ALOGD("%d models are using music buffer", + stdev->music_buffer_enable); goto exit; - + } err = setup_music_buffer(stdev->odsp_hdl); if (err != 0) { stdev->music_buffer_enable--; ALOGE("Failed to load music buffer package"); - goto exit; } } } else { @@ -846,14 +843,15 @@ static int setup_buffer(struct knowles_sound_trigger_device *stdev, goto exit; } stdev->hotword_buffer_enable--; - if (stdev->hotword_buffer_enable != 0) + if (stdev->hotword_buffer_enable != 0) { + ALOGD("hotword buffer is still used by %d models", + stdev->hotword_buffer_enable); goto exit; - + } err = destroy_howord_buffer(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to unload hotword buffer package"); - goto exit; } } else if ((check_uuid_equality(model->uuid, stdev->ambient_model_uuid)) @@ -863,13 +861,14 @@ static int setup_buffer(struct knowles_sound_trigger_device *stdev, goto exit; } stdev->music_buffer_enable--; - if (stdev->music_buffer_enable != 0) + if (stdev->music_buffer_enable != 0) { + ALOGD("music buffer is still used by %d models", + stdev->music_buffer_enable); goto exit; - + } err = destroy_music_buffer(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to unload music buffer package"); - goto exit; } } } @@ -889,20 +888,17 @@ static int destroy_package(struct knowles_sound_trigger_device *stdev, err = destroy_chre_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to destroy CHRE package"); - goto exit; } } } else if (check_uuid_equality(model->uuid, stdev->hotword_model_uuid)) { err = tear_hotword_state(stdev->odsp_hdl, HOTWORD_MASK); if (err != 0) { ALOGE("Failed to tear Hotword state"); - goto exit; } err = flush_model(stdev->odsp_hdl, model->kw_id); if (err != 0) { ALOGE("Failed to flush Hotword model"); - goto exit; } stdev->current_enable = stdev->current_enable & ~HOTWORD_MASK; @@ -910,7 +906,6 @@ static int destroy_package(struct knowles_sound_trigger_device *stdev, err = destroy_hotword_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to destroy Hotword package"); - goto exit; } } @@ -918,13 +913,11 @@ static int destroy_package(struct knowles_sound_trigger_device *stdev, err = tear_hotword_state(stdev->odsp_hdl, WAKEUP_MASK); if (err != 0) { ALOGE("Failed to tear Wakeup state"); - goto exit; } err = flush_model(stdev->odsp_hdl, model->kw_id); if (err != 0) { ALOGE("Failed to flush Wakeup model"); - goto exit; } stdev->current_enable = stdev->current_enable & ~WAKEUP_MASK; @@ -932,7 +925,6 @@ static int destroy_package(struct knowles_sound_trigger_device *stdev, err = destroy_hotword_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to destroy Hotword package"); - goto exit; } } @@ -940,13 +932,11 @@ static int destroy_package(struct knowles_sound_trigger_device *stdev, err = tear_ambient_state(stdev->odsp_hdl, AMBIENT_MASK); if (err != 0) { ALOGE("Failed to tear Ambient state"); - goto exit; } err = flush_model(stdev->odsp_hdl, model->kw_id); if (err != 0) { ALOGE("Failed to flush Ambient model"); - goto exit; } stdev->current_enable = stdev->current_enable & ~AMBIENT_MASK; @@ -954,20 +944,17 @@ static int destroy_package(struct knowles_sound_trigger_device *stdev, err = destroy_ambient_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to destroy Ambient package"); - goto exit; } } } else if (check_uuid_equality(model->uuid, stdev->entity_model_uuid)) { err = tear_ambient_state(stdev->odsp_hdl, ENTITY_MASK); if (err != 0) { ALOGE("Failed to tear Entity state"); - goto exit; } err = flush_model(stdev->odsp_hdl, model->kw_id); if (err != 0) { ALOGE("Failed to flush Entity model"); - goto exit; } stdev->current_enable = stdev->current_enable & ~ENTITY_MASK; @@ -975,11 +962,9 @@ static int destroy_package(struct knowles_sound_trigger_device *stdev, err = destroy_ambient_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to destroy Ambient package"); - goto exit; } } } -exit: return err; } @@ -1059,49 +1044,41 @@ static int async_setup_aec(struct knowles_sound_trigger_device *stdev) INTERNAL_OSCILLATOR); if (ret != 0) { ALOGE("Failed to disable mic route with INT OSC"); - goto exit; } } ret = setup_src_plugin(stdev->odsp_hdl, SRC_AMP_REF); if (ret != 0) { ALOGE("Failed to load SRC-amp package"); - goto exit; } ret = enable_src_route(stdev->route_hdl, true, SRC_AMP_REF); if (ret != 0) { ALOGE("Failed to enable SRC-amp route"); - goto exit; } ret = setup_aec_package(stdev->odsp_hdl); if (ret != 0) { ALOGE("Failed to load AEC package"); - goto exit; } ret = enable_bargein_route(stdev->route_hdl, true); if (ret != 0) { ALOGE("Failed to enable buffer route"); - goto exit; } if (is_mic_controlled_by_ahal(stdev) == false) { ret = enable_amp_ref_route(stdev->route_hdl, true, STRM_16K); if (ret != 0) { ALOGE("Failed to enable amp-ref route"); - goto exit; } ret = enable_mic_route(stdev->route_hdl, true, EXTERNAL_OSCILLATOR); if (ret != 0) { ALOGE("Failed to enable mic route with EXT OSC"); - goto exit; } } else { // main mic is turned by media recording ret = enable_amp_ref_route(stdev->route_hdl, true, STRM_48K); if (ret != 0) { ALOGE("Failed to enable amp-ref route"); - goto exit; } } stdev->is_bargein_route_enabled = true; @@ -1111,13 +1088,11 @@ static int async_setup_aec(struct knowles_sound_trigger_device *stdev) !stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to tear old buffer route"); - goto exit; } ret = set_hotword_buffer_route(stdev->route_hdl, stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to enable buffer route"); - goto exit; } } @@ -1126,13 +1101,11 @@ static int async_setup_aec(struct knowles_sound_trigger_device *stdev) !stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to tear old music buffer route"); - goto exit; } ret = set_music_buffer_route(stdev->route_hdl, stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to enable buffer route"); - goto exit; } } @@ -1145,7 +1118,6 @@ static int async_setup_aec(struct knowles_sound_trigger_device *stdev) !stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to tear old package route"); - goto exit; } // resetup the package route with bargein ret = set_package_route(stdev, @@ -1153,7 +1125,6 @@ static int async_setup_aec(struct knowles_sound_trigger_device *stdev) stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to enable package route"); - goto exit; } } } @@ -1161,7 +1132,6 @@ static int async_setup_aec(struct knowles_sound_trigger_device *stdev) ALOGD("%s: Bargein is already enabled", __func__); } -exit: return ret; } @@ -1180,58 +1150,50 @@ static int handle_input_source(struct knowles_sound_trigger_device *stdev, strmt = STRM_48K; } - /* - *[TODO] Add correct error return value for input source route - * b/119390722 for tracing. - */ if (enable) { + /* + * Setup the sources include microphone, SampleRate Converter + * and Barge-in if necessary. + * The SRC-mic and SRC-amp must be enabled before barge-in route. + * That avoid the frame alignment conflict of AEC module. + */ if (stdev->is_mic_route_enabled == false) { err = check_and_setup_src_package(stdev); if (err != 0) { - ALOGE("Fail to setup src Package"); - goto exit; + ALOGE("Failed to load SRC package"); } err = setup_src_plugin(stdev->odsp_hdl, SRC_MIC); if (err != 0) { - ALOGE("Failed to load SRC package"); - goto exit; + ALOGE("Failed to create SRC-mic plugin"); } err = enable_src_route(stdev->route_hdl, true, SRC_MIC); if (err != 0) { ALOGE("Failed to enable SRC-mic route"); - goto exit; } } if (stdev->rx_active_count > 0 && stdev->is_bargein_route_enabled == false) { err = setup_src_plugin(stdev->odsp_hdl, SRC_AMP_REF); if (err != 0) { - ALOGE("Failed to load SRC-amp package"); - goto exit; + ALOGE("Failed to create SRC-amp plugin"); } err = enable_src_route(stdev->route_hdl, true, SRC_AMP_REF); if (err != 0) { ALOGE("Failed to enable SRC-amp route"); - goto exit; } err = setup_aec_package(stdev->odsp_hdl); if (err != 0) { ALOGE("Failed to load AEC package"); - // We didn't load AEC package so don't setup the routes - goto exit; } - // Enable the bargein route if not enabled err = enable_bargein_route(stdev->route_hdl, true); if (err != 0) { - ALOGE("Failed to enable buffer route"); - goto exit; + ALOGE("Failed to enable barge-in route"); } err = enable_amp_ref_route(stdev->route_hdl, true, strmt); if (err != 0) { - ALOGE("Failed to amp-ref route"); - goto exit; + ALOGE("Failed to enable amp-ref route"); } stdev->is_bargein_route_enabled = true; } @@ -1240,78 +1202,123 @@ static int handle_input_source(struct knowles_sound_trigger_device *stdev, err = enable_mic_route(stdev->route_hdl, true, ct); if (err != 0) { ALOGE("Failed to enable mic route"); - goto exit; } } stdev->is_mic_route_enabled = true; } } else { if (!is_any_model_active(stdev)) { - ALOGD("None of keywords are active"); + ALOGD("None of model are active"); if (stdev->rx_active_count > 0 && stdev->is_bargein_route_enabled == true) { - // Just disable the route and update the route status but retain - // bargein status err = enable_bargein_route(stdev->route_hdl, false); if (err != 0) { - ALOGE("Failed to disable bargein route"); - goto exit; + ALOGE("Failed to disable barge-in route"); } err = destroy_aec_package(stdev->odsp_hdl); if (err != 0) { - ALOGE("Failed to unload AEC package"); - goto exit; + ALOGE("Failed to destroy AEC package"); } err = enable_src_route(stdev->route_hdl, false, SRC_AMP_REF); if (err != 0) { ALOGE("Failed to disable SRC-amp route"); - goto exit; } err = destroy_src_plugin(stdev->odsp_hdl, SRC_AMP_REF); if (err != 0) { - ALOGE("Failed to unload SRC-amp package"); - goto exit; + ALOGE("Failed to destroy SRC-amp package"); } err = enable_amp_ref_route(stdev->route_hdl, false, strmt); if (err != 0) { ALOGE("Failed to amp-ref route"); - goto exit; } stdev->is_bargein_route_enabled = false; } if (stdev->is_mic_route_enabled == true) { - // Close SRC package err = enable_src_route(stdev->route_hdl, false, SRC_MIC); if (err != 0) { ALOGE("Failed to disable SRC-mic route"); - goto exit; } err = destroy_src_plugin(stdev->odsp_hdl, SRC_MIC); if (err != 0) { - ALOGE("Failed to unload SRC-mic package"); - goto exit; + ALOGE("Failed to destroy SRC-mic package"); } if (is_mic_controlled_by_ahal(stdev) == false) { err = enable_mic_route(stdev->route_hdl, false, ct); if (err != 0) { ALOGE("Failed to disable mic route"); - goto exit; } } stdev->is_mic_route_enabled = false; err = check_and_destroy_src_package(stdev); if (err != 0) { - ALOGE("Fail to destroy src Package"); - goto exit; + ALOGE("Failed to destroy src package"); } } } } -exit: return err; } +// Helper functions for audio_device_info + +int list_length(const struct listnode *list) +{ + struct listnode *node; + int length = 0; + + if (list == NULL) { + return 0; + } + + list_for_each (node, list) { + ++length; + } + return length; +} + +/* + * If single device in devices list is equal to passed type + * type should represent a single device. + */ +bool is_single_device_type_equal(struct listnode *devices, + audio_devices_t type) +{ + if (devices == NULL) + return false; + + if (list_length(devices) == 1) { + struct listnode *node = devices->next; + struct audio_device_info *item = node_to_item(node, struct audio_device_info, list); + if (item != NULL && (item->type == type)) + return true; + } + return false; +} + +/* + * Check if a device with given type is present in devices list + */ +bool compare_device_type(struct listnode *devices, audio_devices_t device_type) +{ + struct listnode *node; + struct audio_device_info *item = NULL; + + if (devices == NULL) + return false; + + list_for_each (node, devices) { + item = node_to_item(node, struct audio_device_info, list); + if (item != NULL && (item->type == device_type)) { + ALOGV("%s: device types %d match", __func__, device_type); + return true; + } + } + return false; +} + +// End of helper functions for audio_device_info + static void update_rx_conditions(struct knowles_sound_trigger_device *stdev, audio_event_type_t event, struct audio_event_info *config) @@ -1323,7 +1330,7 @@ static void update_rx_conditions(struct knowles_sound_trigger_device *stdev, ALOGW("%s: unexpected rx inactive event", __func__); } } else if (event == AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE) { - if (!(config->device_info.device & AUDIO_DEVICE_OUT_SPEAKER)) { + if (!compare_device_type(&config->device_info.devices, AUDIO_DEVICE_OUT_SPEAKER)) { ALOGD("%s: Playback device doesn't include SPEAKER.", __func__); } else { @@ -1385,7 +1392,7 @@ static void update_sthal_conditions(struct knowles_sound_trigger_device *stdev, if (stdev->is_concurrent_capture == true && stdev->is_ahal_in_voice_voip_mode == false && stdev->is_con_mic_route_enabled == false && - config->device_info.device == ST_DEVICE_HANDSET_MIC) { + is_single_device_type_equal(&config->device_info.devices, ST_DEVICE_HANDSET_MIC)) { ALOGD("%s: enable mic concurrency", __func__); stdev->is_con_mic_route_enabled = true; } @@ -1470,26 +1477,22 @@ static bool do_handle_functions(struct knowles_sound_trigger_device *stdev, ret = enable_amp_ref_route(stdev->route_hdl, false, STRM_16K); if (ret != 0) { ALOGE("Failed to disable amp-ref route"); - goto exit; } ret = enable_mic_route(stdev->route_hdl, false, EXTERNAL_OSCILLATOR); if (ret != 0) { ALOGE("Failed to disable mic route with EXT OSC"); - goto exit; } ret = enable_amp_ref_route(stdev->route_hdl, true, STRM_48K); if (ret != 0) { ALOGE("Failed to enable amp-ref route"); - goto exit; } } else { ret = enable_mic_route(stdev->route_hdl, false, INTERNAL_OSCILLATOR); if (ret != 0) { ALOGE("Failed to disable mic route with INT OSC"); - goto exit; } } } else { @@ -1543,26 +1546,22 @@ static bool do_handle_functions(struct knowles_sound_trigger_device *stdev, ret = enable_amp_ref_route(stdev->route_hdl, false, STRM_48K); if (ret != 0) { ALOGE("Failed to disable amp-ref route"); - goto exit; } ret = enable_mic_route(stdev->route_hdl, true, EXTERNAL_OSCILLATOR); if (ret != 0) { ALOGE("Failed to enable mic route with EXT OSC"); - goto exit; } // turn on amp-ref with 16khz ret = enable_amp_ref_route(stdev->route_hdl, true, STRM_16K); if (ret != 0) { ALOGE("Failed to enable amp-ref route"); - goto exit; } } else { ret = enable_mic_route(stdev->route_hdl, true, INTERNAL_OSCILLATOR); if (ret != 0) { ALOGE("Failed to enable mic route with INT OSC"); - goto exit; } } } else { @@ -1572,7 +1571,6 @@ static bool do_handle_functions(struct knowles_sound_trigger_device *stdev, } } -exit: ALOGD("-%s-: pre %d, cur %d, event %d", __func__, pre_mode, cur_mode, event); return ret; } @@ -1906,7 +1904,7 @@ static int start_sensor_model(struct knowles_sound_trigger_device * stdev) // If firmware crashed when we are waiting if (stdev->is_st_hal_ready == false) { - err = -EAGAIN; + err = -ENODEV; goto exit; } @@ -1914,7 +1912,7 @@ static int start_sensor_model(struct knowles_sound_trigger_device * stdev) ALOGE("%s: ERROR: Waited for %ds but we didn't get the event from " "Host 1, and fw reset is not yet complete", __func__, SENSOR_CREATE_WAIT_TIME_IN_S * SENSOR_CREATE_WAIT_MAX_COUNT); - err = -EAGAIN; + err = -ENODEV; goto exit; } @@ -2004,7 +2002,7 @@ static int start_chre_model(struct knowles_sound_trigger_device *stdev, // If firmware crashed when we are waiting if (stdev->is_st_hal_ready == false) { - err = -EAGAIN; + err = -ENODEV; goto exit; } @@ -2012,7 +2010,7 @@ static int start_chre_model(struct knowles_sound_trigger_device *stdev, ALOGE("%s: ERROR: Waited for %ds but we didn't get the event from " "Host 1, and fw reset is not yet complete", __func__, CHRE_CREATE_WAIT_TIME_IN_S * CHRE_CREATE_WAIT_MAX_COUNT); - err = -EAGAIN; + err = -ENODEV; goto exit; } @@ -2253,6 +2251,8 @@ static void *callback_thread_loop(void *context) if (fw_status == IAXXX_FW_ACTIVE) { stdev->is_st_hal_ready = false; + // query version during reset progress. + stdev->hotword_version = get_hotword_version(stdev->odsp_hdl); // reset the firmware and wait for firmware download complete err = reset_fw(stdev->odsp_hdl); if (err == -1) { @@ -2264,16 +2264,29 @@ static void *callback_thread_loop(void *context) // Firmware has crashed wait till it recovers stdev->is_st_hal_ready = false; } else if (fw_status == IAXXX_FW_IDLE) { - stdev->route_hdl = audio_route_init(stdev->snd_crd_num, + stdev->hotword_version = get_hotword_version(stdev->odsp_hdl); + if (stdev->hotword_version == HOTWORD_DEFAULT_VER) { + /* This is unlikely use-case, the codec is abnormal at the beginning + * reset_fw the firmware to recovery. + */ + stdev->is_st_hal_ready = false; + err = reset_fw(stdev->odsp_hdl); + if (err == -1) { + ALOGE("%s: ERROR: Failed to reset the firmware %d(%s)", + __func__, errno, strerror(errno)); + } + stdev->fw_reset_done_by_hal = true; + } else { + stdev->route_hdl = audio_route_init(stdev->snd_crd_num, stdev->mixer_path_xml); - if (stdev->route_hdl == NULL) { - ALOGE("Failed to init the audio_route library"); - goto exit; + if (stdev->route_hdl == NULL) { + ALOGE("Failed to init the audio_route library"); + goto exit; + } + set_default_apll_clk(stdev->mixer); + setup_slpi_wakeup_event(stdev->odsp_hdl, true); + stdev->is_st_hal_ready = true; } - - set_default_apll_clk(stdev->mixer); - setup_slpi_wakeup_event(stdev->odsp_hdl, true); - stdev->is_st_hal_ready = true; } pthread_mutex_unlock(&stdev->lock); @@ -2300,12 +2313,8 @@ static void *callback_thread_loop(void *context) err = get_event(stdev->odsp_hdl, &ge); if (err == 0) { if (ge.event_id == OK_GOOGLE_KW_ID) { - ALOGD("Eventid received is OK_GOOGLE_KW_ID %d", - OK_GOOGLE_KW_ID); kwid = OK_GOOGLE_KW_ID; } else if (ge.event_id == AMBIENT_KW_ID) { - ALOGD("Eventid received is AMBIENT_KW_ID %d", - AMBIENT_KW_ID); kwid = AMBIENT_KW_ID; reset_ambient_plugin(stdev->odsp_hdl); } else if (ge.event_id == OSLO_EP_DISCONNECT) { @@ -2343,18 +2352,13 @@ static void *callback_thread_loop(void *context) } break; } else if (ge.event_id == ENTITY_KW_ID) { - ALOGD("Eventid received is ENTITY_KW_ID %d", - ENTITY_KW_ID); kwid = ENTITY_KW_ID; } else if (ge.event_id == WAKEUP_KW_ID) { - ALOGD("Eventid received is WAKEUP_KW_ID %d", - WAKEUP_KW_ID); kwid = WAKEUP_KW_ID; } else { ALOGE("Unknown event id received, ignoring %d", ge.event_id); } - stdev->last_detected_model_type = kwid; break; } else { ALOGE("get_event failed with error %d", err); @@ -2366,6 +2370,7 @@ static void *callback_thread_loop(void *context) * was genuine firmware crash and we don't need to reinit * the audio route library. */ + ALOGD("Firmware has redownloaded, start the recovery"); if (stdev->fw_reset_done_by_hal == true) { stdev->route_hdl = audio_route_init(stdev->snd_crd_num, stdev->mixer_path_xml); @@ -2377,11 +2382,11 @@ static void *callback_thread_loop(void *context) stdev->fw_reset_done_by_hal = false; } - ALOGD("Firmware has redownloaded, start the recovery"); int err = crash_recovery(stdev); if (err != 0) { ALOGE("Crash recovery failed"); } + pthread_cond_signal(&stdev->firmware_ready_cond); } else if (strstr(msg + i, IAXXX_FW_DWNLD_SUCCESS_STR)) { ALOGD("Firmware downloaded successfully"); stdev->is_st_hal_ready = true; @@ -2442,7 +2447,8 @@ static void *callback_thread_loop(void *context) // We need to send this only once, so reset now stdev->models[idx].is_state_query = false; } - if (stdev->models[idx].type == SOUND_MODEL_TYPE_KEYPHRASE) { + if (stdev->models[idx].type == SOUND_MODEL_TYPE_KEYPHRASE && + stdev->adnc_strm_handle[idx] == 0) { struct sound_trigger_phrase_recognition_event *event; event = (struct sound_trigger_phrase_recognition_event*) stdev_keyphrase_event_alloc( @@ -2455,17 +2461,20 @@ static void *callback_thread_loop(void *context) ALOGD("Sending recognition callback for id %d", kwid); + /* Exit the critical section of interaction with + * firmware, release the lock to avoid deadlock + * when processing recognition event */ + pthread_mutex_unlock(&stdev->lock); model->recognition_callback(&event->common, model->recognition_cookie); - // Update the config so that it will be used - // during the streaming - stdev->last_keyword_detected_config = model->config; + pthread_mutex_lock(&stdev->lock); free(event); } else { ALOGE("Failed to allocate memory for the event"); } - } else if (stdev->models[idx].type == SOUND_MODEL_TYPE_GENERIC) { + } else if (stdev->models[idx].type == SOUND_MODEL_TYPE_GENERIC && + stdev->adnc_strm_handle[idx] == 0) { struct sound_trigger_generic_recognition_event *event; event = (struct sound_trigger_generic_recognition_event*) stdev_generic_event_alloc( @@ -2479,16 +2488,19 @@ static void *callback_thread_loop(void *context) ALOGD("Sending recognition callback for id %d", kwid); + /* Exit the critical section of interaction with + * firmware, release the lock to avoid deadlock + * when processing recognition event */ + pthread_mutex_unlock(&stdev->lock); model->recognition_callback(&event->common, model->recognition_cookie); - // Update the config so that it will be used - // during the streaming - stdev->last_keyword_detected_config = model->config; - + pthread_mutex_lock(&stdev->lock); free(event); } else { ALOGE("Failed to allocate memory for the event"); } + } else if (stdev->adnc_strm_handle[idx] != 0) { + ALOGD("model %d is streaming.", idx); } } else { ALOGE("Invalid id or keyword is not active, Subsume the event"); @@ -2529,23 +2541,75 @@ static int stdev_get_properties( ALOGV("+%s+", __func__); if (properties == NULL) return -EINVAL; - memcpy(properties, &hw_properties, sizeof(struct sound_trigger_properties)); + memcpy(properties, &hw_properties.base, sizeof(struct sound_trigger_properties)); ALOGV("-%s-", __func__); return 0; } +/* Insert a decimal numeral for Prefix into the beginning of String. + Length specifies the total number of bytes available at str. +*/ +static int int_prefix_str(char *str, size_t str_len, int prefix, const char *prefix_format) +{ + int prefix_len = snprintf(NULL, 0, prefix_format, prefix); + size_t str_cur_len = strlen(str); + + if (str_len < prefix_len + str_cur_len + 1) + { + ALOGE("%s: Error, not enough space in string to insert prefix: %d, %s\n", + __func__, prefix, str); + return -1; + } + + // Move the string to make room for the prefix. + memmove(str + prefix_len, str, str_cur_len + 1); + + /* Remember the first character, because snprintf will overwrite it with a + null character. + */ + char tmp = str[0]; + + snprintf(str, prefix_len + 1, prefix_format, prefix); + str[prefix_len] = tmp; + return 0; +} + +static const struct sound_trigger_properties_header* stdev_get_properties_extended( + const struct sound_trigger_hw_device *dev __unused) +{ + struct knowles_sound_trigger_device *stdev = + (struct knowles_sound_trigger_device *)dev; + ALOGV("+%s+", __func__); + pthread_mutex_lock(&stdev->lock); + if (hw_properties.header.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_3) { + hw_properties.base.version = stdev->hotword_version; + + /* Per GMS requirement new to Android R, the supported_model_arch field + must be the Google hotword firmware version comma separated with the + supported_model_arch platform identifier. + */ + int_prefix_str(hw_properties.supported_model_arch, SOUND_TRIGGER_MAX_STRING_LEN, + hw_properties.base.version, "%u,"); + ALOGW("SoundTrigger supported model arch identifier is %s", + hw_properties.supported_model_arch); + } else { + ALOGE("STHAL Version is %u", hw_properties.header.version); + pthread_mutex_unlock(&stdev->lock); + return NULL; + } + + pthread_mutex_unlock(&stdev->lock); + ALOGV("-%s-", __func__); + return &hw_properties.header; +} + + static int stop_recognition(struct knowles_sound_trigger_device *stdev, sound_model_handle_t handle) { int status = 0; struct model_info *model = &stdev->models[handle]; - if (stdev->is_st_hal_ready == false) { - ALOGE("%s: ST HAL is not ready yet", __func__); - status = -EAGAIN; - goto exit; - } - if (model->config != NULL) { dereg_hal_event_session(model->config, handle); free(model->config); @@ -2619,17 +2683,15 @@ static int stdev_load_sound_model(const struct sound_trigger_hw_device *dev, int ret = 0; int kw_model_sz = 0; int i = 0; - + sound_trigger_uuid_t empty_uuid = {0}; unsigned char *kw_buffer = NULL; ALOGD("+%s+", __func__); pthread_mutex_lock(&stdev->lock); - if (stdev->is_st_hal_ready == false) { - ALOGE("%s: ST HAL is not ready yet", __func__); - ret = -EAGAIN; + ret = check_firmware_ready(stdev); + if (ret != 0) goto exit; - } if (handle == NULL || sound_model == NULL) { ALOGE("%s: handle/sound_model is NULL", __func__); @@ -2644,6 +2706,12 @@ static int stdev_load_sound_model(const struct sound_trigger_hw_device *dev, goto exit; } + if (check_uuid_equality(sound_model->vendor_uuid, empty_uuid)) { + ALOGE("%s Invalid vendor uuid", __func__); + ret = -EINVAL; + goto exit; + } + // When a delayed CHRE/Oslo destroy process is in progress, // we should not skip the new model and return the existing handle // which will be destroyed soon. @@ -2718,13 +2786,13 @@ static int stdev_load_sound_model(const struct sound_trigger_hw_device *dev, } stdev->models[i].kw_id = USELESS_KW_ID; } else { - ALOGE("%s: ERROR: unknown keyword model file", __func__); + ALOGE("%s: ERROR: unknown model uuid", __func__); ret = -EINVAL; goto error; } *handle = i; - ALOGV("%s: Loading keyword model handle(%d) type(%d)", __func__, + ALOGV("%s: Loading model handle(%d) type(%d)", __func__, *handle, sound_model->type); // This will need to be replaced with UUID once they are fixed stdev->models[i].model_handle = *handle; @@ -2765,11 +2833,9 @@ static int stdev_unload_sound_model(const struct sound_trigger_hw_device *dev, ALOGD("+%s handle %d+", __func__, handle); pthread_mutex_lock(&stdev->lock); - if (stdev->is_st_hal_ready == false) { - ALOGE("%s: ST HAL is not ready yet", __func__); - ret = -EAGAIN; + ret = check_firmware_ready(stdev); + if (ret != 0) goto exit; - } // Just confirm the model was previously loaded if (stdev->models[handle].is_loaded == false) { @@ -2910,14 +2976,11 @@ static int stdev_start_recognition( struct model_info *model = &stdev->models[handle]; ALOGD("%s stdev %p, sound model %d", __func__, stdev, handle); - pthread_mutex_lock(&stdev->lock); - if (stdev->is_st_hal_ready == false) { - ALOGE("%s: ST HAL is not ready yet", __func__); - status = -EAGAIN; + status = check_firmware_ready(stdev); + if (status != 0) goto exit; - } if (callback == NULL) { ALOGE("%s: recognition_callback is null", __func__); @@ -2972,7 +3035,6 @@ static int stdev_start_recognition( status = check_and_setup_buffer_package(stdev); if (status != 0) { ALOGE("%s: ERROR: Failed to load the buffer package", __func__); - goto exit; } model->is_active = true; @@ -3013,6 +3075,37 @@ exit: return status; } +static int stdev_start_recognition_extended( + const struct sound_trigger_hw_device *dev, + sound_model_handle_t sound_model_handle, + const struct sound_trigger_recognition_config_header *header, + recognition_callback_t callback, + void *cookie) +{ + struct sound_trigger_recognition_config_extended_1_3 *config_1_3 = + (struct sound_trigger_recognition_config_extended_1_3 *)header; + int status = 0; + + if (header->version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_3) { + /* Use old version before we have real usecase */ + ALOGD("%s: Running 2_3", __func__); + status = stdev_start_recognition(dev, sound_model_handle, + &config_1_3->base, + callback, + cookie); + } else { + /* Rollback into old start recognition */ + ALOGD("%s: Running 2_1", __func__); + status = stdev_start_recognition(dev, sound_model_handle, + &config_1_3->base, + callback, + cookie); + } + + return status; +} + + static int stdev_stop_recognition( const struct sound_trigger_hw_device *dev, sound_model_handle_t handle) @@ -3020,8 +3113,12 @@ static int stdev_stop_recognition( struct knowles_sound_trigger_device *stdev = (struct knowles_sound_trigger_device *)dev; int status = 0; - pthread_mutex_lock(&stdev->lock); ALOGD("+%s sound model %d+", __func__, handle); + pthread_mutex_lock(&stdev->lock); + + status = check_firmware_ready(stdev); + if (status != 0) + goto exit; status = stop_recognition(stdev, handle); @@ -3057,23 +3154,26 @@ static int stdev_get_model_state(const struct sound_trigger_hw_device *dev, ALOGD("+%s+", __func__); pthread_mutex_lock(&stdev->lock); - if (!stdev->opened) { - ALOGE("%s: stdev isn't initialized", __func__); - ret = -ENODEV; + ret = check_firmware_ready(stdev); + if (ret != 0) goto exit; - } - if (stdev->is_st_hal_ready == false) { - ALOGE("%s: ST HAL is not ready yet", __func__); + if (!stdev->opened) { + ALOGE("%s: stdev isn't initialized", __func__); ret = -ENODEV; goto exit; } - if (model->is_active == false) { + if (model->is_active == false && + !is_uuid_in_recover_list(stdev, sound_model_handle)) { ALOGE("%s: ERROR: %d model is not active", __func__, sound_model_handle); ret = -ENOSYS; goto exit; + } else if (is_uuid_in_recover_list(stdev, sound_model_handle)) { + ALOGD("%s: Ignore %d model request due to call active", + __func__, sound_model_handle); + goto exit; } if (model->is_state_query == true) { @@ -3114,6 +3214,38 @@ exit: return ret; } +static int stdev_query_parameter( + const struct sound_trigger_hw_device *dev __unused, + sound_model_handle_t sound_model_handle __unused, + sound_trigger_model_parameter_t model_param __unused, + sound_trigger_model_parameter_range_t* param_range) +{ + ALOGW("%s: NOT SUPPORTED", __func__); + param_range->is_supported = false; + return 0; +} + +static int stdev_set_parameter( + const struct sound_trigger_hw_device *dev __unused, + sound_model_handle_t sound_model_handle __unused, + sound_trigger_model_parameter_t model_param __unused, + int32_t value __unused) +{ + ALOGW("%s: NOT SUPPORTED", __func__); + return -EINVAL; +} + +static int stdev_get_parameter( + const struct sound_trigger_hw_device *dev __unused, + sound_model_handle_t sound_model_handle __unused, + sound_trigger_model_parameter_t model_param __unused, + int32_t* value __unused) +{ + ALOGW("%s: NOT SUPPORTED", __func__); + return -EINVAL; +} + + static int stdev_close(hw_device_t *device) { struct knowles_sound_trigger_device *stdev = @@ -3122,18 +3254,16 @@ static int stdev_close(hw_device_t *device) ALOGD("+%s+", __func__); pthread_mutex_lock(&stdev->lock); + ret = check_firmware_ready(stdev); + if (ret != 0) + goto exit; + if (!stdev->opened) { ALOGE("%s: device already closed", __func__); ret = -EFAULT; goto exit; } - if (stdev->is_st_hal_ready == false) { - ALOGE("%s: ST HAL is not ready yet", __func__); - ret = -EAGAIN; - goto exit; - } - setup_slpi_wakeup_event(stdev->odsp_hdl, false); stdev->opened = false; @@ -3158,20 +3288,6 @@ exit: return ret; } -__attribute__ ((visibility ("default"))) -audio_io_handle_t stdev_get_audio_handle() -{ - if (g_stdev.last_keyword_detected_config == NULL) { - ALOGI("%s: Config is NULL so returning audio handle as 0", __func__); - return 0; - } - - ALOGI("%s: Audio Handle is %d", - __func__, g_stdev.last_keyword_detected_config->capture_handle); - - return g_stdev.last_keyword_detected_config->capture_handle; -} - static int open_streaming_lib(struct knowles_sound_trigger_device *stdev) { int ret = 0; @@ -3273,7 +3389,7 @@ static int find_sound_card() { const char *snd_card_name; struct mixer *mixer = NULL; bool card_verifed[MAX_SND_CARD] = {false}; - const int retry_limit = property_get_int32("audio.snd_card.open.retries", + const int retry_limit = property_get_int32("vendor.audio.snd_card.open.retries", RETRY_NUMBER); ALOGD("+%s+", __func__); @@ -3420,15 +3536,20 @@ static int stdev_open(const hw_module_t *module, const char *name, } stdev->device.common.tag = HARDWARE_DEVICE_TAG; - stdev->device.common.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_2; + stdev->device.common.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_3; stdev->device.common.module = (struct hw_module_t *)module; stdev->device.common.close = stdev_close; stdev->device.get_properties = stdev_get_properties; stdev->device.load_sound_model = stdev_load_sound_model; stdev->device.unload_sound_model = stdev_unload_sound_model; stdev->device.start_recognition = stdev_start_recognition; + stdev->device.start_recognition_extended = stdev_start_recognition_extended; stdev->device.stop_recognition = stdev_stop_recognition; stdev->device.get_model_state = stdev_get_model_state; + stdev->device.query_parameter = stdev_query_parameter; + stdev->device.set_parameter = stdev_set_parameter; + stdev->device.get_parameter = stdev_get_parameter; + stdev->device.get_properties_extended = stdev_get_properties_extended; stdev->opened = true; /* Initialize all member variable */ @@ -3440,7 +3561,6 @@ static int stdev_open(const hw_module_t *module, const char *name, stdev->models[i].data_sz = 0; stdev->models[i].is_loaded = false; stdev->models[i].is_active = false; - stdev->last_keyword_detected_config = NULL; stdev->models[i].is_state_query = false; } @@ -3459,7 +3579,7 @@ static int stdev_open(const hw_module_t *module, const char *name, stdev->recover_model_list = 0; stdev->rx_active_count = 0; stdev->is_ahal_media_recording = false; - stdev->is_concurrent_capture = hw_properties.concurrent_capture; + stdev->is_concurrent_capture = hw_properties.base.concurrent_capture; stdev->is_sensor_destroy_in_prog = false; stdev->ss_timer_created = false; @@ -3469,6 +3589,7 @@ static int stdev_open(const hw_module_t *module, const char *name, stdev->snd_crd_num = snd_card_num; stdev->fw_reset_done_by_hal = false; + stdev->hotword_version = 0; str_to_uuid(HOTWORD_AUDIO_MODEL, &stdev->hotword_model_uuid); str_to_uuid(WAKEUP_MODEL, &stdev->wakeup_model_uuid); @@ -3600,7 +3721,6 @@ int sound_trigger_hw_call_back(audio_event_type_t event, !stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to tear old package route"); - goto exit; } // resetup the package route with out bargein ret = set_package_route(stdev, @@ -3608,7 +3728,6 @@ int sound_trigger_hw_call_back(audio_event_type_t event, stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to enable package route"); - goto exit; } } } @@ -3619,13 +3738,11 @@ int sound_trigger_hw_call_back(audio_event_type_t event, !stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to tear old buffer route"); - goto exit; } ret = set_hotword_buffer_route(stdev->route_hdl, stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to enable buffer route"); - goto exit; } } @@ -3634,64 +3751,54 @@ int sound_trigger_hw_call_back(audio_event_type_t event, !stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to tear old music buffer route"); - goto exit; } ret = set_music_buffer_route(stdev->route_hdl, stdev->is_bargein_route_enabled); if (ret != 0) { ALOGE("Failed to enable buffer route"); - goto exit; } } ret = enable_bargein_route(stdev->route_hdl, false); if (ret != 0) { ALOGE("Failed to enable buffer route"); - goto exit; } ret = destroy_aec_package(stdev->odsp_hdl); if (ret != 0) { - ALOGE("Failed to unload AEC package"); - goto exit; + ALOGE("Failed to destroy AEC package"); } ret = enable_src_route(stdev->route_hdl, false, SRC_AMP_REF); if (ret != 0) { ALOGE("Failed to disable SRC-amp route"); - goto exit; } ret = destroy_src_plugin(stdev->odsp_hdl, SRC_AMP_REF); if (ret != 0) { - ALOGE("Failed to unload SRC-amp package"); - goto exit; + ALOGE("Failed to destroy SRC-amp package"); } if (is_mic_controlled_by_ahal(stdev) == false) { ret = enable_amp_ref_route(stdev->route_hdl, false, STRM_16K); if (ret != 0) { ALOGE("Failed to disable amp-ref route"); - goto exit; } ret = enable_mic_route(stdev->route_hdl, false, EXTERNAL_OSCILLATOR); if (ret != 0) { ALOGE("Failed to disable mic route with INT OSC"); - goto exit; } ret = enable_mic_route(stdev->route_hdl, true, INTERNAL_OSCILLATOR); if (ret != 0) { ALOGE("Failed to enable mic route with EXT OSC"); - goto exit; } } else { // main mic is turned by media record, close it by 48khz ret = enable_amp_ref_route(stdev->route_hdl, false, STRM_48K); if (ret != 0) { ALOGE("Failed to disable amp-ref route"); - goto exit; } } } else { @@ -3784,6 +3891,12 @@ int sound_trigger_hw_call_back(audio_event_type_t event, } } + /* There is not valid model to provide pcm samples. */ + if (i == MAX_MODELS) { + ret = -EINVAL; + goto exit; + } + /* Open Stream Driver */ if (index != -1 && stdev->adnc_strm_handle[index] == 0) { if (stdev->adnc_strm_open == NULL) { @@ -3791,24 +3904,25 @@ int sound_trigger_hw_call_back(audio_event_type_t event, } else { bool keyword_stripping_enabled = false; int stream_end_point; - switch (stdev->last_detected_model_type) { - case OK_GOOGLE_KW_ID: - stream_end_point = CVQ_ENDPOINT; - break; - case AMBIENT_KW_ID: - case ENTITY_KW_ID: - stream_end_point = MUSIC_BUF_ENDPOINT; - break; - default: - stream_end_point = CVQ_ENDPOINT; - break; - }; + if (check_uuid_equality(stdev->models[index].uuid, + stdev->hotword_model_uuid)) { + stream_end_point = CVQ_ENDPOINT; + } else if (check_uuid_equality(stdev->models[index].uuid, + stdev->ambient_model_uuid)) { + stream_end_point = MUSIC_BUF_ENDPOINT; + } else if (check_uuid_equality(stdev->models[index].uuid, + stdev->entity_model_uuid)) { + stream_end_point = MUSIC_BUF_ENDPOINT; + } else { + stream_end_point = CVQ_ENDPOINT; + } stdev->adnc_strm_handle[index] = stdev->adnc_strm_open( keyword_stripping_enabled, 0, stream_end_point); if (stdev->adnc_strm_handle[index]) { - ALOGD("Successfully opened adnc strm! index %d handle %d", - index, config->u.aud_info.ses_info->capture_handle); + ALOGD("Opened adnc index %d handle %d endpoint 0x%x", + index, config->u.aud_info.ses_info->capture_handle, + stream_end_point); stdev->is_streaming++; clock_gettime(CLOCK_REALTIME, &stdev->adnc_strm_last_read[index]); diff --git a/sound_trigger_intf.h b/sound_trigger_intf.h index 3da77f0..02782d9 100644 --- a/sound_trigger_intf.h +++ b/sound_trigger_intf.h @@ -17,6 +17,7 @@ #ifndef SOUND_TRIGGER_INTF_H #define SOUND_TRIGGER_INTF_H +#include <cutils/list.h> #include <hardware/sound_trigger.h> #include "tinyalsa/asoundlib.h" @@ -31,8 +32,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 STHAL_PROP_API_VERSION_2_0 MAKE_HAL_VERSION(2, 0) +#define STHAL_PROP_API_CURRENT_VERSION STHAL_PROP_API_VERSION_2_0 #define ST_EVENT_CONFIG_MAX_STR_VALUE 32 @@ -128,8 +129,14 @@ struct sound_trigger_get_param_data { struct str_parms *reply; }; +struct audio_device_info { + struct listnode list; + audio_devices_t type; + char address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; +}; + struct sound_trigger_device_info { - int device; + struct listnode devices; }; struct audio_event_info { diff --git a/tests/oslo_config_test.c b/tests/oslo_config_test.c index c63b4cf..4056218 100644 --- a/tests/oslo_config_test.c +++ b/tests/oslo_config_test.c @@ -149,6 +149,16 @@ static const oslo_settings_t oslo_plugin_settings[] = {OSLO_SENSOR_PARAM_HOST, "plugin_set_host"}, {OSLO_SENSOR_STATE, "plugin_oslo_state"}, {OSLO_SENSOR_CONFIG_RECOVERY_COUNTER, "plugin_config_retries"}, + {OSLO_SENSOR_PARAM_ENABLE_PRESENCE, "plugin_enable_presence"}, + {OSLO_SENSOR_PARAM_ENABLE_REACH, "plugin_enable_reach"}, + {OSLO_SENSOR_PARAM_ENABLE_FLICK, "plugin_enable_flick"}, + {OSLO_SENSOR_PARAM_ENABLE_SWIPE, "plugin_enable_swipe"}, + {OSLO_SENSOR_PARAM_ENABLE_TAP, "plugin_enable_tap"}, + {OSLO_SENSOR_PARAM_ENABLE_AUDIO_FILTER, "plugin_enable_audio_filter"}, + {OSLO_SENSOR_PARAM_ENABLE_WLC_FILTER, "plugin_enable_wlc_filter"}, + {OSLO_SENSOR_PARAM_CPS, "plugin_cps"}, + {OSLO_SENSOR_MAX_POWER_MODE, "plugin_max_power_mode"}, + {OSLO_SENSOR_PARAM_SLPY_TEST_MODE, "plugin_slpy_test_mode"}, }; /* map oslo plugin test mode name to param id */ diff --git a/tests/oslo_iaxxx_sensor_control.h b/tests/oslo_iaxxx_sensor_control.h index fc9e9c5..53c2f62 100644 --- a/tests/oslo_iaxxx_sensor_control.h +++ b/tests/oslo_iaxxx_sensor_control.h @@ -177,6 +177,16 @@ typedef enum oslo_sensor_param_id_e { OSLO_TESTMODE_REACH_FLICK, OSLO_TESTMODE_REACH_SWIPE_FLICK, OSLO_SENSOR_CONFIG_RECOVERY_COUNTER, + OSLO_SENSOR_PARAM_ENABLE_REACH, + OSLO_SENSOR_PARAM_ENABLE_FLICK, + OSLO_SENSOR_PARAM_ENABLE_AUDIO_FILTER, + OSLO_SENSOR_PARAM_ENABLE_WLC_FILTER, + OSLO_SENSOR_PARAM_CPS, + OSLO_SENSOR_MAX_POWER_MODE, + OSLO_SENSOR_PARAM_SLPY_TEST_MODE, + OSLO_SENSOR_PARAM_ENABLE_PRESENCE, + OSLO_SENSOR_PARAM_ENABLE_SWIPE, + OSLO_SENSOR_PARAM_ENABLE_TAP, /* Force enums to be of size int */ OSLO_SENSOR_PARAM_ID_FORCE_SIZE = INT_MAX, |