Merge "Stub HAL now can test abort and fail events" into nyc-dev
This commit is contained in:
commit
17908ca83d
1 changed files with 155 additions and 154 deletions
|
@ -38,7 +38,9 @@
|
||||||
|
|
||||||
// The following commands work with the network port:
|
// The following commands work with the network port:
|
||||||
#define COMMAND_LS "ls"
|
#define COMMAND_LS "ls"
|
||||||
#define COMMAND_TRIGGER "trig" // Argument: model index.
|
#define COMMAND_RECOGNITION_TRIGGER "trig" // Argument: model index.
|
||||||
|
#define COMMAND_RECOGNITION_ABORT "abort" // Argument: model index.
|
||||||
|
#define COMMAND_RECOGNITION_FAILURE "fail" // Argument: model index.
|
||||||
#define COMMAND_UPDATE "update" // Argument: model index.
|
#define COMMAND_UPDATE "update" // Argument: model index.
|
||||||
#define COMMAND_CLOSE "close" // Close just closes the network port, keeps thread running.
|
#define COMMAND_CLOSE "close" // Close just closes the network port, keeps thread running.
|
||||||
#define COMMAND_END "end" // Closes connection and stops the thread.
|
#define COMMAND_END "end" // Closes connection and stops the thread.
|
||||||
|
@ -76,7 +78,7 @@ static const struct sound_trigger_properties hw_properties = {
|
||||||
RECOGNITION_MODE_VOICE_TRIGGER, // recognition_modes
|
RECOGNITION_MODE_VOICE_TRIGGER, // recognition_modes
|
||||||
false, // capture_transition
|
false, // capture_transition
|
||||||
0, // max_buffer_ms
|
0, // max_buffer_ms
|
||||||
false, // concurrent_capture
|
true, // concurrent_capture
|
||||||
false, // trigger_in_event
|
false, // trigger_in_event
|
||||||
0 // power_consumption_mw
|
0 // power_consumption_mw
|
||||||
};
|
};
|
||||||
|
@ -113,6 +115,25 @@ struct stub_sound_trigger_device {
|
||||||
int next_sound_model_id;
|
int next_sound_model_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns model at the given index, null otherwise (error, doesn't exist, etc).
|
||||||
|
// Note that here index starts from zero.
|
||||||
|
struct recognition_context* fetch_model_at_index(
|
||||||
|
struct stub_sound_trigger_device* stdev, int index) {
|
||||||
|
ALOGI("%s", __func__);
|
||||||
|
struct recognition_context *model_context = NULL;
|
||||||
|
struct recognition_context *last_model_context = stdev->root_model_context;
|
||||||
|
unsigned int model_index = 0;
|
||||||
|
while(last_model_context) {
|
||||||
|
if (model_index == index) {
|
||||||
|
model_context = last_model_context;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last_model_context = last_model_context->next;
|
||||||
|
model_index++;
|
||||||
|
}
|
||||||
|
return model_context;
|
||||||
|
}
|
||||||
|
|
||||||
/* Will reuse ids when overflow occurs */
|
/* Will reuse ids when overflow occurs */
|
||||||
static sound_model_handle_t generate_sound_model_handle(const struct sound_trigger_hw_device *dev) {
|
static sound_model_handle_t generate_sound_model_handle(const struct sound_trigger_hw_device *dev) {
|
||||||
struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
|
struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
|
||||||
|
@ -126,93 +147,142 @@ static sound_model_handle_t generate_sound_model_handle(const struct sound_trigg
|
||||||
|
|
||||||
bool parse_socket_data(int conn_socket, struct stub_sound_trigger_device* stdev);
|
bool parse_socket_data(int conn_socket, struct stub_sound_trigger_device* stdev);
|
||||||
|
|
||||||
static char *sound_trigger_event_alloc(sound_model_handle_t handle,
|
static char *sound_trigger_keyphrase_event_alloc(sound_model_handle_t handle,
|
||||||
sound_trigger_sound_model_type_t model_type,
|
struct sound_trigger_recognition_config *config,
|
||||||
struct sound_trigger_recognition_config *config) {
|
int recognition_status) {
|
||||||
char *data;
|
char *data;
|
||||||
if (model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
|
struct sound_trigger_phrase_recognition_event *event;
|
||||||
struct sound_trigger_phrase_recognition_event *event;
|
data = (char *)calloc(1, sizeof(struct sound_trigger_phrase_recognition_event));
|
||||||
data = (char *)calloc(1, sizeof(struct sound_trigger_phrase_recognition_event));
|
if (!data)
|
||||||
if (!data)
|
|
||||||
return NULL;
|
|
||||||
event = (struct sound_trigger_phrase_recognition_event *)data;
|
|
||||||
event->common.status = RECOGNITION_STATUS_SUCCESS;
|
|
||||||
event->common.type = SOUND_MODEL_TYPE_KEYPHRASE;
|
|
||||||
event->common.model = handle;
|
|
||||||
|
|
||||||
if (config) {
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
event->num_phrases = config->num_phrases;
|
|
||||||
if (event->num_phrases > SOUND_TRIGGER_MAX_PHRASES)
|
|
||||||
event->num_phrases = SOUND_TRIGGER_MAX_PHRASES;
|
|
||||||
for (i=0; i < event->num_phrases; i++)
|
|
||||||
memcpy(&event->phrase_extras[i],
|
|
||||||
&config->phrases[i],
|
|
||||||
sizeof(struct sound_trigger_phrase_recognition_extra));
|
|
||||||
}
|
|
||||||
|
|
||||||
event->num_phrases = 1;
|
|
||||||
event->phrase_extras[0].confidence_level = 100;
|
|
||||||
event->phrase_extras[0].num_levels = 1;
|
|
||||||
event->phrase_extras[0].levels[0].level = 100;
|
|
||||||
event->phrase_extras[0].levels[0].user_id = 0;
|
|
||||||
// Signify that all the data is comming through streaming, not through the buffer.
|
|
||||||
event->common.capture_available = true;
|
|
||||||
event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
|
|
||||||
event->common.audio_config.sample_rate = 16000;
|
|
||||||
event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
|
|
||||||
event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
|
|
||||||
} else if (model_type == SOUND_MODEL_TYPE_GENERIC) {
|
|
||||||
struct sound_trigger_generic_recognition_event *event;
|
|
||||||
data = (char *)calloc(1, sizeof(struct sound_trigger_generic_recognition_event));
|
|
||||||
if (!data)
|
|
||||||
return NULL;
|
|
||||||
event = (struct sound_trigger_generic_recognition_event *)data;
|
|
||||||
event->common.status = RECOGNITION_STATUS_SUCCESS;
|
|
||||||
event->common.type = SOUND_MODEL_TYPE_GENERIC;
|
|
||||||
event->common.model = handle;
|
|
||||||
|
|
||||||
// Signify that all the data is comming through streaming, not through the buffer.
|
|
||||||
event->common.capture_available = true;
|
|
||||||
event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
|
|
||||||
event->common.audio_config.sample_rate = 16000;
|
|
||||||
event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
|
|
||||||
event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
|
|
||||||
} else {
|
|
||||||
ALOGW("No Valid Event Type Known");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
event = (struct sound_trigger_phrase_recognition_event *)data;
|
||||||
|
event->common.status = recognition_status;
|
||||||
|
event->common.type = SOUND_MODEL_TYPE_KEYPHRASE;
|
||||||
|
event->common.model = handle;
|
||||||
|
|
||||||
|
if (config) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
event->num_phrases = config->num_phrases;
|
||||||
|
if (event->num_phrases > SOUND_TRIGGER_MAX_PHRASES)
|
||||||
|
event->num_phrases = SOUND_TRIGGER_MAX_PHRASES;
|
||||||
|
for (i=0; i < event->num_phrases; i++)
|
||||||
|
memcpy(&event->phrase_extras[i],
|
||||||
|
&config->phrases[i],
|
||||||
|
sizeof(struct sound_trigger_phrase_recognition_extra));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event->num_phrases = 1;
|
||||||
|
event->phrase_extras[0].confidence_level = 100;
|
||||||
|
event->phrase_extras[0].num_levels = 1;
|
||||||
|
event->phrase_extras[0].levels[0].level = 100;
|
||||||
|
event->phrase_extras[0].levels[0].user_id = 0;
|
||||||
|
// Signify that all the data is comming through streaming, not through the buffer.
|
||||||
|
event->common.capture_available = true;
|
||||||
|
event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
|
||||||
|
event->common.audio_config.sample_rate = 16000;
|
||||||
|
event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
|
||||||
|
event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_recognition_event(sound_model_handle_t model_handle,
|
static char *sound_trigger_generic_event_alloc(sound_model_handle_t handle,
|
||||||
sound_trigger_sound_model_type_t model_type,
|
struct sound_trigger_recognition_config *config,
|
||||||
recognition_callback_t recognition_callback, void *recognition_cookie,
|
int recognition_status) {
|
||||||
struct sound_trigger_recognition_config *config) {
|
char *data;
|
||||||
if (recognition_callback == NULL) {
|
struct sound_trigger_generic_recognition_event *event;
|
||||||
ALOGI("%s No matching callback for handle %d", __func__, model_handle);
|
data = (char *)calloc(1, sizeof(struct sound_trigger_generic_recognition_event));
|
||||||
|
if (!data)
|
||||||
|
return NULL;
|
||||||
|
event = (struct sound_trigger_generic_recognition_event *)data;
|
||||||
|
event->common.status = recognition_status;
|
||||||
|
event->common.type = SOUND_MODEL_TYPE_GENERIC;
|
||||||
|
event->common.model = handle;
|
||||||
|
|
||||||
|
// Signify that all the data is comming through streaming, not through the buffer.
|
||||||
|
event->common.capture_available = true;
|
||||||
|
event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
|
||||||
|
event->common.audio_config.sample_rate = 16000;
|
||||||
|
event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
|
||||||
|
event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_bad_command_error(int conn_socket, char* command) {
|
||||||
|
int num = snprintf(tmp_write_buffer, PARSE_BUF_LEN, "Bad command received: %s", command);
|
||||||
|
tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0'; // Just to be sure.
|
||||||
|
tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
|
||||||
|
write(conn_socket, tmp_write_buffer, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_string(int conn_socket, char* str) {
|
||||||
|
int num = snprintf(tmp_write_buffer, PARSE_BUF_LEN, "%s", str);
|
||||||
|
tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';
|
||||||
|
tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
|
||||||
|
write(conn_socket, tmp_write_buffer, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_vastr(int conn_socket, char* format, ...) {
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, format);
|
||||||
|
int num = vsnprintf(tmp_write_buffer, PARSE_BUF_LEN, format, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';
|
||||||
|
tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
|
||||||
|
write(conn_socket, tmp_write_buffer, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_recognition_event(int conn_socket, char* buffer, struct stub_sound_trigger_device* stdev,
|
||||||
|
int recognition_status) {
|
||||||
|
ALOGI("%s", __func__);
|
||||||
|
char* model_handle_str = strtok(NULL, " ");
|
||||||
|
if (model_handle_str == NULL) {
|
||||||
|
write_string(conn_socket, "Bad sound model id.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int index = -1;
|
||||||
|
if (sscanf(model_handle_str, "%d", &index) <= 0) {
|
||||||
|
write_vastr(conn_socket, "Unable to parse sound model index: %s\n", model_handle_str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
|
if (index < (int)hw_properties.max_sound_models) {
|
||||||
struct sound_trigger_phrase_recognition_event *event;
|
ALOGI("Going to send trigger for model index #%d", index );
|
||||||
event = (struct sound_trigger_phrase_recognition_event *)
|
struct recognition_context *model_context = fetch_model_at_index(stdev, index);
|
||||||
sound_trigger_event_alloc(model_handle, model_type, config);
|
if (model_context) {
|
||||||
if (event) {
|
if (model_context->recognition_callback == NULL) {
|
||||||
recognition_callback(event, recognition_cookie);
|
ALOGI("%s No matching callback for handle %d", __func__,
|
||||||
free(event);
|
model_context->model_handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model_context->model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
|
||||||
|
struct sound_trigger_phrase_recognition_event *event;
|
||||||
|
event = (struct sound_trigger_phrase_recognition_event *)
|
||||||
|
sound_trigger_keyphrase_event_alloc(model_context->model_handle,
|
||||||
|
model_context->config,
|
||||||
|
recognition_status);
|
||||||
|
if (event) {
|
||||||
|
model_context->recognition_callback(event, model_context->recognition_cookie);
|
||||||
|
free(event);
|
||||||
|
}
|
||||||
|
} else if (model_context->model_type == SOUND_MODEL_TYPE_GENERIC) {
|
||||||
|
struct sound_trigger_generic_recognition_event *event;
|
||||||
|
event = (struct sound_trigger_generic_recognition_event *)
|
||||||
|
sound_trigger_generic_event_alloc(model_context->model_handle,
|
||||||
|
model_context->config,
|
||||||
|
recognition_status);
|
||||||
|
if (event) {
|
||||||
|
model_context->recognition_callback(event, model_context->recognition_cookie);
|
||||||
|
free(event);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ALOGI("Unknown Sound Model Type, No Event to Send");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ALOGI("Sound Model Does Not Exist at this Index: %d", index);
|
||||||
|
write_string(conn_socket, "Sound Model Does Not Exist at given Index.\n");
|
||||||
}
|
}
|
||||||
} else if (model_type == SOUND_MODEL_TYPE_GENERIC) {
|
|
||||||
struct sound_trigger_generic_recognition_event *event;
|
|
||||||
event = (struct sound_trigger_generic_recognition_event *)
|
|
||||||
sound_trigger_event_alloc(model_handle, model_type, config);
|
|
||||||
if (event) {
|
|
||||||
recognition_callback(event, recognition_cookie);
|
|
||||||
free(event);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ALOGI("Unknown Sound Model Type, No Event to Send");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,30 +405,6 @@ static void *control_thread_loop(void *context) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_bad_command_error(int conn_socket, char* command) {
|
|
||||||
int num = snprintf(tmp_write_buffer, PARSE_BUF_LEN, "Bad command received: %s", command);
|
|
||||||
tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0'; // Just to be sure.
|
|
||||||
tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
|
|
||||||
write(conn_socket, tmp_write_buffer, num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_string(int conn_socket, char* str) {
|
|
||||||
int num = snprintf(tmp_write_buffer, PARSE_BUF_LEN, "%s", str);
|
|
||||||
tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';
|
|
||||||
tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
|
|
||||||
write(conn_socket, tmp_write_buffer, num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_vastr(int conn_socket, char* format, ...) {
|
|
||||||
va_list argptr;
|
|
||||||
va_start(argptr, format);
|
|
||||||
int num = vsnprintf(tmp_write_buffer, PARSE_BUF_LEN, format, argptr);
|
|
||||||
va_end(argptr);
|
|
||||||
tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';
|
|
||||||
tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
|
|
||||||
write(conn_socket, tmp_write_buffer, num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void list_models(int conn_socket, char* buffer,
|
void list_models(int conn_socket, char* buffer,
|
||||||
struct stub_sound_trigger_device* stdev) {
|
struct stub_sound_trigger_device* stdev) {
|
||||||
ALOGI("%s", __func__);
|
ALOGI("%s", __func__);
|
||||||
|
@ -394,55 +440,6 @@ void list_models(int conn_socket, char* buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns model at the given index, null otherwise (error, doesn't exist, etc).
|
|
||||||
// Note that here index starts from zero.
|
|
||||||
struct recognition_context* fetch_model_at_index(
|
|
||||||
struct stub_sound_trigger_device* stdev, int index) {
|
|
||||||
ALOGI("%s", __func__);
|
|
||||||
struct recognition_context *model_context = NULL;
|
|
||||||
struct recognition_context *last_model_context = stdev->root_model_context;
|
|
||||||
unsigned int model_index = 0;
|
|
||||||
while(last_model_context) {
|
|
||||||
if (model_index == index) {
|
|
||||||
model_context = last_model_context;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
last_model_context = last_model_context->next;
|
|
||||||
model_index++;
|
|
||||||
}
|
|
||||||
return model_context;
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_trigger(int conn_socket, char* buffer,
|
|
||||||
struct stub_sound_trigger_device* stdev) {
|
|
||||||
ALOGI("%s", __func__);
|
|
||||||
char* model_handle_str = strtok(NULL, " ");
|
|
||||||
if (model_handle_str == NULL) {
|
|
||||||
write_string(conn_socket, "Bad sound model id.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int index = -1;
|
|
||||||
if (sscanf(model_handle_str, "%d", &index) <= 0) {
|
|
||||||
write_vastr(conn_socket, "Unable to parse sound model index: %s\n", model_handle_str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < (int)hw_properties.max_sound_models) {
|
|
||||||
ALOGI("Going to send trigger for model index #%d", index );
|
|
||||||
struct recognition_context *model_context = fetch_model_at_index(stdev, index);
|
|
||||||
if (model_context) {
|
|
||||||
send_recognition_event(model_context->model_handle,
|
|
||||||
model_context->model_type,
|
|
||||||
model_context->recognition_callback,
|
|
||||||
model_context->recognition_cookie,
|
|
||||||
model_context->config);
|
|
||||||
} else {
|
|
||||||
ALOGI("Sound Model Does Not Exist at this Index: %d", index);
|
|
||||||
write_string(conn_socket, "Sound Model Does Not Exist at given Index.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void process_send_model_event(int conn_socket, char* buffer,
|
void process_send_model_event(int conn_socket, char* buffer,
|
||||||
struct stub_sound_trigger_device* stdev) {
|
struct stub_sound_trigger_device* stdev) {
|
||||||
ALOGI("%s", __func__);
|
ALOGI("%s", __func__);
|
||||||
|
@ -502,8 +499,12 @@ bool parse_socket_data(int conn_socket, struct stub_sound_trigger_device* stdev)
|
||||||
write_bad_command_error(conn_socket, command);
|
write_bad_command_error(conn_socket, command);
|
||||||
} else if (strncmp(command, COMMAND_LS, 2) == 0) {
|
} else if (strncmp(command, COMMAND_LS, 2) == 0) {
|
||||||
list_models(conn_socket, buffer, stdev);
|
list_models(conn_socket, buffer, stdev);
|
||||||
} else if (strcmp(command, COMMAND_TRIGGER) == 0) {
|
} else if (strcmp(command, COMMAND_RECOGNITION_TRIGGER) == 0) {
|
||||||
send_trigger(conn_socket, buffer, stdev);
|
send_recognition_event(conn_socket, buffer, stdev, RECOGNITION_STATUS_SUCCESS);
|
||||||
|
} else if (strcmp(command, COMMAND_RECOGNITION_ABORT) == 0) {
|
||||||
|
send_recognition_event(conn_socket, buffer, stdev, RECOGNITION_STATUS_ABORT);
|
||||||
|
} else if (strcmp(command, COMMAND_RECOGNITION_FAILURE) == 0) {
|
||||||
|
send_recognition_event(conn_socket, buffer, stdev, RECOGNITION_STATUS_FAILURE);
|
||||||
} else if (strcmp(command, COMMAND_UPDATE) == 0) {
|
} else if (strcmp(command, COMMAND_UPDATE) == 0) {
|
||||||
process_send_model_event(conn_socket, buffer, stdev);
|
process_send_model_event(conn_socket, buffer, stdev);
|
||||||
} else if (strncmp(command, COMMAND_CLOSE, 5) == 0) {
|
} else if (strncmp(command, COMMAND_CLOSE, 5) == 0) {
|
||||||
|
|
Loading…
Reference in a new issue