1*e01b6f76SAndroid Build Coastguard Worker /*
2*e01b6f76SAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*e01b6f76SAndroid Build Coastguard Worker *
4*e01b6f76SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e01b6f76SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e01b6f76SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e01b6f76SAndroid Build Coastguard Worker *
8*e01b6f76SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e01b6f76SAndroid Build Coastguard Worker *
10*e01b6f76SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e01b6f76SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e01b6f76SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e01b6f76SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e01b6f76SAndroid Build Coastguard Worker * limitations under the License.
15*e01b6f76SAndroid Build Coastguard Worker */
16*e01b6f76SAndroid Build Coastguard Worker
17*e01b6f76SAndroid Build Coastguard Worker
18*e01b6f76SAndroid Build Coastguard Worker /* This HAL simulates triggers from the DSP.
19*e01b6f76SAndroid Build Coastguard Worker * To send a trigger from the command line you can type:
20*e01b6f76SAndroid Build Coastguard Worker *
21*e01b6f76SAndroid Build Coastguard Worker * adb forward tcp:14035 tcp:14035
22*e01b6f76SAndroid Build Coastguard Worker *
23*e01b6f76SAndroid Build Coastguard Worker * telnet localhost 14035
24*e01b6f76SAndroid Build Coastguard Worker *
25*e01b6f76SAndroid Build Coastguard Worker * Commands include:
26*e01b6f76SAndroid Build Coastguard Worker * ls : Lists all models that have been loaded.
27*e01b6f76SAndroid Build Coastguard Worker * trig <uuid> : Sends a recognition event for the model at the given uuid
28*e01b6f76SAndroid Build Coastguard Worker * update <uuid> : Sends a model update event for the model at the given uuid.
29*e01b6f76SAndroid Build Coastguard Worker * close : Closes the network connection.
30*e01b6f76SAndroid Build Coastguard Worker *
31*e01b6f76SAndroid Build Coastguard Worker * To enable this file, you can make with command line parameter
32*e01b6f76SAndroid Build Coastguard Worker * SOUND_TRIGGER_USE_STUB_MODULE=1
33*e01b6f76SAndroid Build Coastguard Worker */
34*e01b6f76SAndroid Build Coastguard Worker
35*e01b6f76SAndroid Build Coastguard Worker #define LOG_TAG "sound_trigger_hw_default"
36*e01b6f76SAndroid Build Coastguard Worker #define LOG_NDEBUG 1
37*e01b6f76SAndroid Build Coastguard Worker #define PARSE_BUF_LEN 1024 // Length of the parsing buffer.S
38*e01b6f76SAndroid Build Coastguard Worker
39*e01b6f76SAndroid Build Coastguard Worker #define EVENT_RECOGNITION 1
40*e01b6f76SAndroid Build Coastguard Worker #define EVENT_SOUND_MODEL 2
41*e01b6f76SAndroid Build Coastguard Worker
42*e01b6f76SAndroid Build Coastguard Worker // The following commands work with the network port:
43*e01b6f76SAndroid Build Coastguard Worker #define COMMAND_LS "ls"
44*e01b6f76SAndroid Build Coastguard Worker #define COMMAND_RECOGNITION_TRIGGER "trig" // Argument: model index.
45*e01b6f76SAndroid Build Coastguard Worker #define COMMAND_RECOGNITION_ABORT "abort" // Argument: model index.
46*e01b6f76SAndroid Build Coastguard Worker #define COMMAND_RECOGNITION_FAILURE "fail" // Argument: model index.
47*e01b6f76SAndroid Build Coastguard Worker #define COMMAND_UPDATE "update" // Argument: model index.
48*e01b6f76SAndroid Build Coastguard Worker #define COMMAND_CLEAR "clear" // Removes all models from the list.
49*e01b6f76SAndroid Build Coastguard Worker #define COMMAND_CLOSE "close" // Close just closes the network port, keeps thread running.
50*e01b6f76SAndroid Build Coastguard Worker #define COMMAND_END "end" // Closes connection and stops the thread.
51*e01b6f76SAndroid Build Coastguard Worker
52*e01b6f76SAndroid Build Coastguard Worker #define ERROR_BAD_COMMAND "Bad command"
53*e01b6f76SAndroid Build Coastguard Worker
54*e01b6f76SAndroid Build Coastguard Worker #include <arpa/inet.h>
55*e01b6f76SAndroid Build Coastguard Worker #include <errno.h>
56*e01b6f76SAndroid Build Coastguard Worker #include <pthread.h>
57*e01b6f76SAndroid Build Coastguard Worker #include <netinet/in.h>
58*e01b6f76SAndroid Build Coastguard Worker #include <stdarg.h>
59*e01b6f76SAndroid Build Coastguard Worker #include <stdio.h>
60*e01b6f76SAndroid Build Coastguard Worker #include <stdlib.h>
61*e01b6f76SAndroid Build Coastguard Worker #include <string.h>
62*e01b6f76SAndroid Build Coastguard Worker #include <sys/prctl.h>
63*e01b6f76SAndroid Build Coastguard Worker #include <sys/types.h>
64*e01b6f76SAndroid Build Coastguard Worker #include <sys/socket.h>
65*e01b6f76SAndroid Build Coastguard Worker #include <unistd.h>
66*e01b6f76SAndroid Build Coastguard Worker
67*e01b6f76SAndroid Build Coastguard Worker #include <log/log.h>
68*e01b6f76SAndroid Build Coastguard Worker
69*e01b6f76SAndroid Build Coastguard Worker #include <hardware/hardware.h>
70*e01b6f76SAndroid Build Coastguard Worker #include <system/sound_trigger.h>
71*e01b6f76SAndroid Build Coastguard Worker #include <hardware/sound_trigger.h>
72*e01b6f76SAndroid Build Coastguard Worker
73*e01b6f76SAndroid Build Coastguard Worker static const struct sound_trigger_properties hw_properties = {
74*e01b6f76SAndroid Build Coastguard Worker "The Android Open Source Project", // implementor
75*e01b6f76SAndroid Build Coastguard Worker "Sound Trigger stub HAL", // description
76*e01b6f76SAndroid Build Coastguard Worker 1, // version
77*e01b6f76SAndroid Build Coastguard Worker { 0xed7a7d60, 0xc65e, 0x11e3, 0x9be4, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
78*e01b6f76SAndroid Build Coastguard Worker 4, // max_sound_models
79*e01b6f76SAndroid Build Coastguard Worker 1, // max_key_phrases
80*e01b6f76SAndroid Build Coastguard Worker 1, // max_users
81*e01b6f76SAndroid Build Coastguard Worker RECOGNITION_MODE_VOICE_TRIGGER, // recognition_modes
82*e01b6f76SAndroid Build Coastguard Worker false, // capture_transition
83*e01b6f76SAndroid Build Coastguard Worker 0, // max_buffer_ms
84*e01b6f76SAndroid Build Coastguard Worker true, // concurrent_capture
85*e01b6f76SAndroid Build Coastguard Worker false, // trigger_in_event
86*e01b6f76SAndroid Build Coastguard Worker 0 // power_consumption_mw
87*e01b6f76SAndroid Build Coastguard Worker };
88*e01b6f76SAndroid Build Coastguard Worker
89*e01b6f76SAndroid Build Coastguard Worker struct recognition_context {
90*e01b6f76SAndroid Build Coastguard Worker // Sound Model information, added in method load_sound_model
91*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t model_handle;
92*e01b6f76SAndroid Build Coastguard Worker sound_trigger_uuid_t model_uuid;
93*e01b6f76SAndroid Build Coastguard Worker sound_trigger_sound_model_type_t model_type;
94*e01b6f76SAndroid Build Coastguard Worker sound_model_callback_t model_callback;
95*e01b6f76SAndroid Build Coastguard Worker void *model_cookie;
96*e01b6f76SAndroid Build Coastguard Worker
97*e01b6f76SAndroid Build Coastguard Worker // Sound Model information, added in start_recognition
98*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_recognition_config *config;
99*e01b6f76SAndroid Build Coastguard Worker recognition_callback_t recognition_callback;
100*e01b6f76SAndroid Build Coastguard Worker void *recognition_cookie;
101*e01b6f76SAndroid Build Coastguard Worker
102*e01b6f76SAndroid Build Coastguard Worker bool model_started;
103*e01b6f76SAndroid Build Coastguard Worker
104*e01b6f76SAndroid Build Coastguard Worker // Next recognition_context in the linked list
105*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *next;
106*e01b6f76SAndroid Build Coastguard Worker };
107*e01b6f76SAndroid Build Coastguard Worker
108*e01b6f76SAndroid Build Coastguard Worker char tmp_write_buffer[PARSE_BUF_LEN];
109*e01b6f76SAndroid Build Coastguard Worker
110*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device {
111*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_hw_device device;
112*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_t lock;
113*e01b6f76SAndroid Build Coastguard Worker
114*e01b6f76SAndroid Build Coastguard Worker // This thread opens a port that can be used to monitor and inject events
115*e01b6f76SAndroid Build Coastguard Worker // into the stub HAL.
116*e01b6f76SAndroid Build Coastguard Worker pthread_t control_thread;
117*e01b6f76SAndroid Build Coastguard Worker
118*e01b6f76SAndroid Build Coastguard Worker // Recognition contexts are stored as a linked list
119*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *root_model_context;
120*e01b6f76SAndroid Build Coastguard Worker
121*e01b6f76SAndroid Build Coastguard Worker int next_sound_model_id;
122*e01b6f76SAndroid Build Coastguard Worker };
123*e01b6f76SAndroid Build Coastguard Worker
check_uuid_equality(sound_trigger_uuid_t uuid1,sound_trigger_uuid_t uuid2)124*e01b6f76SAndroid Build Coastguard Worker static bool check_uuid_equality(sound_trigger_uuid_t uuid1, sound_trigger_uuid_t uuid2) {
125*e01b6f76SAndroid Build Coastguard Worker if (uuid1.timeLow != uuid2.timeLow ||
126*e01b6f76SAndroid Build Coastguard Worker uuid1.timeMid != uuid2.timeMid ||
127*e01b6f76SAndroid Build Coastguard Worker uuid1.timeHiAndVersion != uuid2.timeHiAndVersion ||
128*e01b6f76SAndroid Build Coastguard Worker uuid1.clockSeq != uuid2.clockSeq) {
129*e01b6f76SAndroid Build Coastguard Worker return false;
130*e01b6f76SAndroid Build Coastguard Worker }
131*e01b6f76SAndroid Build Coastguard Worker for (int i = 0; i < 6; i++) {
132*e01b6f76SAndroid Build Coastguard Worker if(uuid1.node[i] != uuid2.node[i]) {
133*e01b6f76SAndroid Build Coastguard Worker return false;
134*e01b6f76SAndroid Build Coastguard Worker }
135*e01b6f76SAndroid Build Coastguard Worker }
136*e01b6f76SAndroid Build Coastguard Worker return true;
137*e01b6f76SAndroid Build Coastguard Worker }
138*e01b6f76SAndroid Build Coastguard Worker
str_to_uuid(char * uuid_str,sound_trigger_uuid_t * uuid)139*e01b6f76SAndroid Build Coastguard Worker bool str_to_uuid(char* uuid_str, sound_trigger_uuid_t* uuid) {
140*e01b6f76SAndroid Build Coastguard Worker if (uuid_str == NULL) {
141*e01b6f76SAndroid Build Coastguard Worker ALOGI("Invalid str_to_uuid input.");
142*e01b6f76SAndroid Build Coastguard Worker return false;
143*e01b6f76SAndroid Build Coastguard Worker }
144*e01b6f76SAndroid Build Coastguard Worker
145*e01b6f76SAndroid Build Coastguard Worker int tmp[10];
146*e01b6f76SAndroid Build Coastguard Worker if (sscanf(uuid_str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
147*e01b6f76SAndroid Build Coastguard Worker tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
148*e01b6f76SAndroid Build Coastguard Worker ALOGI("Invalid UUID, got: %s", uuid_str);
149*e01b6f76SAndroid Build Coastguard Worker return false;
150*e01b6f76SAndroid Build Coastguard Worker }
151*e01b6f76SAndroid Build Coastguard Worker uuid->timeLow = (unsigned int)tmp[0];
152*e01b6f76SAndroid Build Coastguard Worker uuid->timeMid = (unsigned short)tmp[1];
153*e01b6f76SAndroid Build Coastguard Worker uuid->timeHiAndVersion = (unsigned short)tmp[2];
154*e01b6f76SAndroid Build Coastguard Worker uuid->clockSeq = (unsigned short)tmp[3];
155*e01b6f76SAndroid Build Coastguard Worker uuid->node[0] = (unsigned char)tmp[4];
156*e01b6f76SAndroid Build Coastguard Worker uuid->node[1] = (unsigned char)tmp[5];
157*e01b6f76SAndroid Build Coastguard Worker uuid->node[2] = (unsigned char)tmp[6];
158*e01b6f76SAndroid Build Coastguard Worker uuid->node[3] = (unsigned char)tmp[7];
159*e01b6f76SAndroid Build Coastguard Worker uuid->node[4] = (unsigned char)tmp[8];
160*e01b6f76SAndroid Build Coastguard Worker uuid->node[5] = (unsigned char)tmp[9];
161*e01b6f76SAndroid Build Coastguard Worker return true;
162*e01b6f76SAndroid Build Coastguard Worker }
163*e01b6f76SAndroid Build Coastguard Worker
write_bad_command_error(int conn_socket,char * command)164*e01b6f76SAndroid Build Coastguard Worker void write_bad_command_error(int conn_socket, char* command) {
165*e01b6f76SAndroid Build Coastguard Worker int num = snprintf(tmp_write_buffer, PARSE_BUF_LEN, "Bad command received: %s", command);
166*e01b6f76SAndroid Build Coastguard Worker tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0'; // Just to be sure.
167*e01b6f76SAndroid Build Coastguard Worker tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
168*e01b6f76SAndroid Build Coastguard Worker write(conn_socket, tmp_write_buffer, num);
169*e01b6f76SAndroid Build Coastguard Worker }
170*e01b6f76SAndroid Build Coastguard Worker
write_string(int conn_socket,char * str)171*e01b6f76SAndroid Build Coastguard Worker void write_string(int conn_socket, char* str) {
172*e01b6f76SAndroid Build Coastguard Worker int num = snprintf(tmp_write_buffer, PARSE_BUF_LEN, "%s", str);
173*e01b6f76SAndroid Build Coastguard Worker tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';
174*e01b6f76SAndroid Build Coastguard Worker tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
175*e01b6f76SAndroid Build Coastguard Worker write(conn_socket, tmp_write_buffer, num);
176*e01b6f76SAndroid Build Coastguard Worker }
177*e01b6f76SAndroid Build Coastguard Worker
write_vastr(int conn_socket,char * format,...)178*e01b6f76SAndroid Build Coastguard Worker void write_vastr(int conn_socket, char* format, ...) {
179*e01b6f76SAndroid Build Coastguard Worker va_list argptr;
180*e01b6f76SAndroid Build Coastguard Worker va_start(argptr, format);
181*e01b6f76SAndroid Build Coastguard Worker int num = vsnprintf(tmp_write_buffer, PARSE_BUF_LEN, format, argptr);
182*e01b6f76SAndroid Build Coastguard Worker va_end(argptr);
183*e01b6f76SAndroid Build Coastguard Worker tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';
184*e01b6f76SAndroid Build Coastguard Worker tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
185*e01b6f76SAndroid Build Coastguard Worker write(conn_socket, tmp_write_buffer, num);
186*e01b6f76SAndroid Build Coastguard Worker }
187*e01b6f76SAndroid Build Coastguard Worker
print_uuid(sound_trigger_uuid_t uuid)188*e01b6f76SAndroid Build Coastguard Worker static void print_uuid(sound_trigger_uuid_t uuid) {
189*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", __func__, uuid.timeLow, uuid.timeMid,
190*e01b6f76SAndroid Build Coastguard Worker uuid.timeHiAndVersion, uuid.clockSeq, uuid.node[0], uuid.node[1], uuid.node[2],
191*e01b6f76SAndroid Build Coastguard Worker uuid.node[3], uuid.node[4], uuid.node[5]);
192*e01b6f76SAndroid Build Coastguard Worker }
193*e01b6f76SAndroid Build Coastguard Worker
write_uuid(int conn_socket,sound_trigger_uuid_t uuid)194*e01b6f76SAndroid Build Coastguard Worker static void write_uuid(int conn_socket, sound_trigger_uuid_t uuid) {
195*e01b6f76SAndroid Build Coastguard Worker write_vastr(conn_socket, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", uuid.timeLow, uuid.timeMid,
196*e01b6f76SAndroid Build Coastguard Worker uuid.timeHiAndVersion, uuid.clockSeq, uuid.node[0], uuid.node[1], uuid.node[2],
197*e01b6f76SAndroid Build Coastguard Worker uuid.node[3], uuid.node[4], uuid.node[5]);
198*e01b6f76SAndroid Build Coastguard Worker }
199*e01b6f76SAndroid Build Coastguard Worker
200*e01b6f76SAndroid Build Coastguard Worker // Returns model at the given index, null otherwise (error, doesn't exist, etc).
201*e01b6f76SAndroid Build Coastguard Worker // Note that here index starts from zero.
fetch_model_with_handle(struct stub_sound_trigger_device * stdev,sound_model_handle_t * model_handle)202*e01b6f76SAndroid Build Coastguard Worker struct recognition_context* fetch_model_with_handle(
203*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device* stdev, sound_model_handle_t* model_handle) {
204*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
205*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = NULL;
206*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *last_model_context = stdev->root_model_context;
207*e01b6f76SAndroid Build Coastguard Worker while(last_model_context) {
208*e01b6f76SAndroid Build Coastguard Worker if (last_model_context->model_handle == *model_handle) {
209*e01b6f76SAndroid Build Coastguard Worker model_context = last_model_context;
210*e01b6f76SAndroid Build Coastguard Worker break;
211*e01b6f76SAndroid Build Coastguard Worker }
212*e01b6f76SAndroid Build Coastguard Worker last_model_context = last_model_context->next;
213*e01b6f76SAndroid Build Coastguard Worker }
214*e01b6f76SAndroid Build Coastguard Worker return model_context;
215*e01b6f76SAndroid Build Coastguard Worker }
216*e01b6f76SAndroid Build Coastguard Worker
217*e01b6f76SAndroid Build Coastguard Worker // Returns the first model that matches the sound model UUID.
get_model_handle_with_uuid(struct stub_sound_trigger_device * stdev,sound_trigger_uuid_t uuid)218*e01b6f76SAndroid Build Coastguard Worker static sound_model_handle_t* get_model_handle_with_uuid(struct stub_sound_trigger_device* stdev,
219*e01b6f76SAndroid Build Coastguard Worker sound_trigger_uuid_t uuid) {
220*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t* model_handle_str = NULL;
221*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *last_model_context = stdev->root_model_context;
222*e01b6f76SAndroid Build Coastguard Worker while(last_model_context) {
223*e01b6f76SAndroid Build Coastguard Worker if (check_uuid_equality(last_model_context->model_uuid, uuid)) {
224*e01b6f76SAndroid Build Coastguard Worker model_handle_str = &last_model_context->model_handle;
225*e01b6f76SAndroid Build Coastguard Worker break;
226*e01b6f76SAndroid Build Coastguard Worker }
227*e01b6f76SAndroid Build Coastguard Worker last_model_context = last_model_context->next;
228*e01b6f76SAndroid Build Coastguard Worker }
229*e01b6f76SAndroid Build Coastguard Worker return model_handle_str;
230*e01b6f76SAndroid Build Coastguard Worker }
231*e01b6f76SAndroid Build Coastguard Worker
232*e01b6f76SAndroid Build Coastguard Worker /* Will reuse ids when overflow occurs */
generate_sound_model_handle(const struct sound_trigger_hw_device * dev)233*e01b6f76SAndroid Build Coastguard Worker static sound_model_handle_t generate_sound_model_handle(const struct sound_trigger_hw_device *dev) {
234*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
235*e01b6f76SAndroid Build Coastguard Worker int new_id = stdev->next_sound_model_id;
236*e01b6f76SAndroid Build Coastguard Worker ++stdev->next_sound_model_id;
237*e01b6f76SAndroid Build Coastguard Worker if (stdev->next_sound_model_id == 0) {
238*e01b6f76SAndroid Build Coastguard Worker stdev->next_sound_model_id = 1;
239*e01b6f76SAndroid Build Coastguard Worker }
240*e01b6f76SAndroid Build Coastguard Worker return (sound_model_handle_t) new_id;
241*e01b6f76SAndroid Build Coastguard Worker }
242*e01b6f76SAndroid Build Coastguard Worker
243*e01b6f76SAndroid Build Coastguard Worker bool parse_socket_data(int conn_socket, struct stub_sound_trigger_device* stdev);
244*e01b6f76SAndroid Build Coastguard Worker static void unload_all_sound_models(struct stub_sound_trigger_device *stdev);
245*e01b6f76SAndroid Build Coastguard Worker
sound_trigger_keyphrase_event_alloc(sound_model_handle_t handle,struct sound_trigger_recognition_config * config,int recognition_status)246*e01b6f76SAndroid Build Coastguard Worker static char *sound_trigger_keyphrase_event_alloc(sound_model_handle_t handle,
247*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_recognition_config *config,
248*e01b6f76SAndroid Build Coastguard Worker int recognition_status) {
249*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_phrase_recognition_event *event =
250*e01b6f76SAndroid Build Coastguard Worker calloc(1, sizeof(struct sound_trigger_phrase_recognition_event));
251*e01b6f76SAndroid Build Coastguard Worker if (!event)
252*e01b6f76SAndroid Build Coastguard Worker return NULL;
253*e01b6f76SAndroid Build Coastguard Worker event->common.status = recognition_status;
254*e01b6f76SAndroid Build Coastguard Worker event->common.type = SOUND_MODEL_TYPE_KEYPHRASE;
255*e01b6f76SAndroid Build Coastguard Worker event->common.model = handle;
256*e01b6f76SAndroid Build Coastguard Worker
257*e01b6f76SAndroid Build Coastguard Worker if (config) {
258*e01b6f76SAndroid Build Coastguard Worker unsigned int i;
259*e01b6f76SAndroid Build Coastguard Worker
260*e01b6f76SAndroid Build Coastguard Worker event->num_phrases = config->num_phrases;
261*e01b6f76SAndroid Build Coastguard Worker if (event->num_phrases > SOUND_TRIGGER_MAX_PHRASES)
262*e01b6f76SAndroid Build Coastguard Worker event->num_phrases = SOUND_TRIGGER_MAX_PHRASES;
263*e01b6f76SAndroid Build Coastguard Worker for (i=0; i < event->num_phrases; i++)
264*e01b6f76SAndroid Build Coastguard Worker memcpy(&event->phrase_extras[i],
265*e01b6f76SAndroid Build Coastguard Worker &config->phrases[i],
266*e01b6f76SAndroid Build Coastguard Worker sizeof(struct sound_trigger_phrase_recognition_extra));
267*e01b6f76SAndroid Build Coastguard Worker }
268*e01b6f76SAndroid Build Coastguard Worker
269*e01b6f76SAndroid Build Coastguard Worker event->num_phrases = 1;
270*e01b6f76SAndroid Build Coastguard Worker event->phrase_extras[0].confidence_level = 100;
271*e01b6f76SAndroid Build Coastguard Worker event->phrase_extras[0].num_levels = 1;
272*e01b6f76SAndroid Build Coastguard Worker event->phrase_extras[0].levels[0].level = 100;
273*e01b6f76SAndroid Build Coastguard Worker event->phrase_extras[0].levels[0].user_id = 0;
274*e01b6f76SAndroid Build Coastguard Worker // Signify that all the data is comming through streaming, not through the buffer.
275*e01b6f76SAndroid Build Coastguard Worker event->common.capture_available = true;
276*e01b6f76SAndroid Build Coastguard Worker event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
277*e01b6f76SAndroid Build Coastguard Worker event->common.audio_config.sample_rate = 16000;
278*e01b6f76SAndroid Build Coastguard Worker event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
279*e01b6f76SAndroid Build Coastguard Worker event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
280*e01b6f76SAndroid Build Coastguard Worker return (char*) event;
281*e01b6f76SAndroid Build Coastguard Worker }
282*e01b6f76SAndroid Build Coastguard Worker
sound_trigger_generic_event_alloc(sound_model_handle_t handle,struct sound_trigger_recognition_config * config,int recognition_status)283*e01b6f76SAndroid Build Coastguard Worker static char *sound_trigger_generic_event_alloc(sound_model_handle_t handle,
284*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_recognition_config *config,
285*e01b6f76SAndroid Build Coastguard Worker int recognition_status) {
286*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_generic_recognition_event *event =
287*e01b6f76SAndroid Build Coastguard Worker calloc(1, sizeof(struct sound_trigger_generic_recognition_event));
288*e01b6f76SAndroid Build Coastguard Worker if (!event)
289*e01b6f76SAndroid Build Coastguard Worker return NULL;
290*e01b6f76SAndroid Build Coastguard Worker event->common.status = recognition_status;
291*e01b6f76SAndroid Build Coastguard Worker event->common.type = SOUND_MODEL_TYPE_GENERIC;
292*e01b6f76SAndroid Build Coastguard Worker event->common.model = handle;
293*e01b6f76SAndroid Build Coastguard Worker
294*e01b6f76SAndroid Build Coastguard Worker // Signify that all the data is comming through streaming, not through the buffer.
295*e01b6f76SAndroid Build Coastguard Worker event->common.capture_available = true;
296*e01b6f76SAndroid Build Coastguard Worker event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
297*e01b6f76SAndroid Build Coastguard Worker event->common.audio_config.sample_rate = 16000;
298*e01b6f76SAndroid Build Coastguard Worker event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
299*e01b6f76SAndroid Build Coastguard Worker event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
300*e01b6f76SAndroid Build Coastguard Worker return (char*) event;
301*e01b6f76SAndroid Build Coastguard Worker }
302*e01b6f76SAndroid Build Coastguard Worker
send_event_with_handle(sound_model_handle_t * model_handle_str,struct stub_sound_trigger_device * stdev,int event_type,int status)303*e01b6f76SAndroid Build Coastguard Worker void send_event_with_handle(sound_model_handle_t* model_handle_str,
304*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device* stdev, int event_type,
305*e01b6f76SAndroid Build Coastguard Worker int status) {
306*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
307*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = fetch_model_with_handle(stdev, model_handle_str);
308*e01b6f76SAndroid Build Coastguard Worker if (model_context) {
309*e01b6f76SAndroid Build Coastguard Worker if (event_type == EVENT_RECOGNITION) {
310*e01b6f76SAndroid Build Coastguard Worker if (model_context->recognition_callback == NULL) {
311*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s No matching callback", __func__);
312*e01b6f76SAndroid Build Coastguard Worker return;
313*e01b6f76SAndroid Build Coastguard Worker }
314*e01b6f76SAndroid Build Coastguard Worker
315*e01b6f76SAndroid Build Coastguard Worker if (model_context->model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
316*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_phrase_recognition_event *event;
317*e01b6f76SAndroid Build Coastguard Worker event = (struct sound_trigger_phrase_recognition_event *)
318*e01b6f76SAndroid Build Coastguard Worker sound_trigger_keyphrase_event_alloc(model_context->model_handle,
319*e01b6f76SAndroid Build Coastguard Worker model_context->config, status);
320*e01b6f76SAndroid Build Coastguard Worker if (event) {
321*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_callback(event, model_context->recognition_cookie);
322*e01b6f76SAndroid Build Coastguard Worker free(event);
323*e01b6f76SAndroid Build Coastguard Worker }
324*e01b6f76SAndroid Build Coastguard Worker } else if (model_context->model_type == SOUND_MODEL_TYPE_GENERIC) {
325*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_generic_recognition_event *event;
326*e01b6f76SAndroid Build Coastguard Worker event = (struct sound_trigger_generic_recognition_event *)
327*e01b6f76SAndroid Build Coastguard Worker sound_trigger_generic_event_alloc(model_context->model_handle,
328*e01b6f76SAndroid Build Coastguard Worker model_context->config, status);
329*e01b6f76SAndroid Build Coastguard Worker if (event) {
330*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_callback(event, model_context->recognition_cookie);
331*e01b6f76SAndroid Build Coastguard Worker free(event);
332*e01b6f76SAndroid Build Coastguard Worker }
333*e01b6f76SAndroid Build Coastguard Worker } else {
334*e01b6f76SAndroid Build Coastguard Worker ALOGI("Unknown Sound Model Type, No Event to Send");
335*e01b6f76SAndroid Build Coastguard Worker }
336*e01b6f76SAndroid Build Coastguard Worker } else if (event_type == EVENT_SOUND_MODEL) {
337*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_model_event *event =
338*e01b6f76SAndroid Build Coastguard Worker calloc(1, sizeof(struct sound_trigger_model_event));
339*e01b6f76SAndroid Build Coastguard Worker if (!event) {
340*e01b6f76SAndroid Build Coastguard Worker ALOGW("%s Could not allocate event", __func__);
341*e01b6f76SAndroid Build Coastguard Worker return;
342*e01b6f76SAndroid Build Coastguard Worker }
343*e01b6f76SAndroid Build Coastguard Worker
344*e01b6f76SAndroid Build Coastguard Worker event->status = SOUND_MODEL_STATUS_UPDATED;
345*e01b6f76SAndroid Build Coastguard Worker event->model = model_context->model_handle;
346*e01b6f76SAndroid Build Coastguard Worker if (event) {
347*e01b6f76SAndroid Build Coastguard Worker model_context->model_callback(&event, model_context->model_cookie);
348*e01b6f76SAndroid Build Coastguard Worker free(event);
349*e01b6f76SAndroid Build Coastguard Worker }
350*e01b6f76SAndroid Build Coastguard Worker }
351*e01b6f76SAndroid Build Coastguard Worker } else {
352*e01b6f76SAndroid Build Coastguard Worker ALOGI("No model for this handle");
353*e01b6f76SAndroid Build Coastguard Worker }
354*e01b6f76SAndroid Build Coastguard Worker }
355*e01b6f76SAndroid Build Coastguard Worker
send_event(int conn_socket,struct stub_sound_trigger_device * stdev,int event_type,int status)356*e01b6f76SAndroid Build Coastguard Worker static void send_event(int conn_socket, struct stub_sound_trigger_device* stdev, int event_type,
357*e01b6f76SAndroid Build Coastguard Worker int status) {
358*e01b6f76SAndroid Build Coastguard Worker char* model_uuid_str = strtok(NULL, " \r\n");
359*e01b6f76SAndroid Build Coastguard Worker sound_trigger_uuid_t model_uuid;
360*e01b6f76SAndroid Build Coastguard Worker if (str_to_uuid(model_uuid_str, &model_uuid)) {
361*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t* model_handle_str = get_model_handle_with_uuid(stdev, model_uuid);
362*e01b6f76SAndroid Build Coastguard Worker if (model_handle_str == NULL) {
363*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s Bad sound model handle.", __func__);
364*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "Bad sound model handle.\n");
365*e01b6f76SAndroid Build Coastguard Worker return;
366*e01b6f76SAndroid Build Coastguard Worker }
367*e01b6f76SAndroid Build Coastguard Worker send_event_with_handle(model_handle_str, stdev, event_type, status);
368*e01b6f76SAndroid Build Coastguard Worker } else {
369*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s Not a valid UUID", __func__);
370*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "Not a valid UUID.\n");
371*e01b6f76SAndroid Build Coastguard Worker }
372*e01b6f76SAndroid Build Coastguard Worker }
373*e01b6f76SAndroid Build Coastguard Worker
recognition_callback_exists(struct stub_sound_trigger_device * stdev)374*e01b6f76SAndroid Build Coastguard Worker static bool recognition_callback_exists(struct stub_sound_trigger_device *stdev) {
375*e01b6f76SAndroid Build Coastguard Worker bool callback_found = false;
376*e01b6f76SAndroid Build Coastguard Worker if (stdev->root_model_context) {
377*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *current_model_context = stdev->root_model_context;
378*e01b6f76SAndroid Build Coastguard Worker while(current_model_context) {
379*e01b6f76SAndroid Build Coastguard Worker if (current_model_context->recognition_callback != NULL) {
380*e01b6f76SAndroid Build Coastguard Worker callback_found = true;
381*e01b6f76SAndroid Build Coastguard Worker break;
382*e01b6f76SAndroid Build Coastguard Worker }
383*e01b6f76SAndroid Build Coastguard Worker current_model_context = current_model_context->next;
384*e01b6f76SAndroid Build Coastguard Worker }
385*e01b6f76SAndroid Build Coastguard Worker }
386*e01b6f76SAndroid Build Coastguard Worker return callback_found;
387*e01b6f76SAndroid Build Coastguard Worker }
388*e01b6f76SAndroid Build Coastguard Worker
get_model_context(struct stub_sound_trigger_device * stdev,sound_model_handle_t handle)389*e01b6f76SAndroid Build Coastguard Worker static struct recognition_context * get_model_context(struct stub_sound_trigger_device *stdev,
390*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t handle) {
391*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = NULL;
392*e01b6f76SAndroid Build Coastguard Worker if (stdev->root_model_context) {
393*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *current_model_context = stdev->root_model_context;
394*e01b6f76SAndroid Build Coastguard Worker while(current_model_context) {
395*e01b6f76SAndroid Build Coastguard Worker if (current_model_context->model_handle == handle) {
396*e01b6f76SAndroid Build Coastguard Worker model_context = current_model_context;
397*e01b6f76SAndroid Build Coastguard Worker break;
398*e01b6f76SAndroid Build Coastguard Worker }
399*e01b6f76SAndroid Build Coastguard Worker current_model_context = current_model_context->next;
400*e01b6f76SAndroid Build Coastguard Worker }
401*e01b6f76SAndroid Build Coastguard Worker }
402*e01b6f76SAndroid Build Coastguard Worker return model_context;
403*e01b6f76SAndroid Build Coastguard Worker }
404*e01b6f76SAndroid Build Coastguard Worker
control_thread_loop(void * context)405*e01b6f76SAndroid Build Coastguard Worker static void *control_thread_loop(void *context) {
406*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)context;
407*e01b6f76SAndroid Build Coastguard Worker struct sockaddr_in incoming_info;
408*e01b6f76SAndroid Build Coastguard Worker struct sockaddr_in self_info;
409*e01b6f76SAndroid Build Coastguard Worker int self_socket;
410*e01b6f76SAndroid Build Coastguard Worker socklen_t sock_size = sizeof(struct sockaddr_in);
411*e01b6f76SAndroid Build Coastguard Worker memset(&self_info, 0, sizeof(self_info));
412*e01b6f76SAndroid Build Coastguard Worker self_info.sin_family = AF_INET;
413*e01b6f76SAndroid Build Coastguard Worker self_info.sin_addr.s_addr = htonl(INADDR_ANY);
414*e01b6f76SAndroid Build Coastguard Worker self_info.sin_port = htons(14035);
415*e01b6f76SAndroid Build Coastguard Worker
416*e01b6f76SAndroid Build Coastguard Worker bool exit = false;
417*e01b6f76SAndroid Build Coastguard Worker while(!exit) {
418*e01b6f76SAndroid Build Coastguard Worker int received_count;
419*e01b6f76SAndroid Build Coastguard Worker int requested_count = 2;
420*e01b6f76SAndroid Build Coastguard Worker char buffer[requested_count];
421*e01b6f76SAndroid Build Coastguard Worker ALOGE("Opening socket");
422*e01b6f76SAndroid Build Coastguard Worker self_socket = socket(AF_INET, SOCK_STREAM, 0);
423*e01b6f76SAndroid Build Coastguard Worker if (self_socket < 0) {
424*e01b6f76SAndroid Build Coastguard Worker ALOGE("Error on socket creation: %s", strerror(errno));
425*e01b6f76SAndroid Build Coastguard Worker exit = true;
426*e01b6f76SAndroid Build Coastguard Worker } else {
427*e01b6f76SAndroid Build Coastguard Worker ALOGI("Socket created");
428*e01b6f76SAndroid Build Coastguard Worker }
429*e01b6f76SAndroid Build Coastguard Worker
430*e01b6f76SAndroid Build Coastguard Worker int reuse = 1;
431*e01b6f76SAndroid Build Coastguard Worker if (setsockopt(self_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) {
432*e01b6f76SAndroid Build Coastguard Worker ALOGE("setsockopt(SO_REUSEADDR) failed");
433*e01b6f76SAndroid Build Coastguard Worker }
434*e01b6f76SAndroid Build Coastguard Worker
435*e01b6f76SAndroid Build Coastguard Worker int bind_result = bind(self_socket, (struct sockaddr *)&self_info, sizeof(struct sockaddr));
436*e01b6f76SAndroid Build Coastguard Worker if (bind_result < 0) {
437*e01b6f76SAndroid Build Coastguard Worker ALOGE("Error on bind");
438*e01b6f76SAndroid Build Coastguard Worker exit = true;
439*e01b6f76SAndroid Build Coastguard Worker }
440*e01b6f76SAndroid Build Coastguard Worker
441*e01b6f76SAndroid Build Coastguard Worker int listen_result = listen(self_socket, 1);
442*e01b6f76SAndroid Build Coastguard Worker if (listen_result < 0) {
443*e01b6f76SAndroid Build Coastguard Worker ALOGE("Error on Listen");
444*e01b6f76SAndroid Build Coastguard Worker exit = true;
445*e01b6f76SAndroid Build Coastguard Worker }
446*e01b6f76SAndroid Build Coastguard Worker
447*e01b6f76SAndroid Build Coastguard Worker while(!exit) {
448*e01b6f76SAndroid Build Coastguard Worker int con_socket = accept(self_socket, (struct sockaddr *)&incoming_info, &sock_size);
449*e01b6f76SAndroid Build Coastguard Worker if (!con_socket) {
450*e01b6f76SAndroid Build Coastguard Worker ALOGE("Lost socket, cannot send trigger");
451*e01b6f76SAndroid Build Coastguard Worker break;
452*e01b6f76SAndroid Build Coastguard Worker }
453*e01b6f76SAndroid Build Coastguard Worker ALOGI("Connection from %s", inet_ntoa(incoming_info.sin_addr));
454*e01b6f76SAndroid Build Coastguard Worker if (!parse_socket_data(con_socket, stdev)) {
455*e01b6f76SAndroid Build Coastguard Worker ALOGI("Done processing commands over network. Stopping thread.");
456*e01b6f76SAndroid Build Coastguard Worker exit = true;
457*e01b6f76SAndroid Build Coastguard Worker }
458*e01b6f76SAndroid Build Coastguard Worker close(con_socket);
459*e01b6f76SAndroid Build Coastguard Worker }
460*e01b6f76SAndroid Build Coastguard Worker ALOGE("Closing socket");
461*e01b6f76SAndroid Build Coastguard Worker close(self_socket);
462*e01b6f76SAndroid Build Coastguard Worker }
463*e01b6f76SAndroid Build Coastguard Worker
464*e01b6f76SAndroid Build Coastguard Worker return NULL;
465*e01b6f76SAndroid Build Coastguard Worker }
466*e01b6f76SAndroid Build Coastguard Worker
list_models(int conn_socket,char * buffer,struct stub_sound_trigger_device * stdev)467*e01b6f76SAndroid Build Coastguard Worker void list_models(int conn_socket, char* buffer,
468*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device* stdev) {
469*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
470*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *last_model_context = stdev->root_model_context;
471*e01b6f76SAndroid Build Coastguard Worker unsigned int model_index = 0;
472*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "-----------------------\n");
473*e01b6f76SAndroid Build Coastguard Worker if (!last_model_context) {
474*e01b6f76SAndroid Build Coastguard Worker ALOGI("ZERO Models exist.");
475*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "Zero models exist.\n");
476*e01b6f76SAndroid Build Coastguard Worker }
477*e01b6f76SAndroid Build Coastguard Worker while (last_model_context) {
478*e01b6f76SAndroid Build Coastguard Worker write_vastr(conn_socket, "Model Index: %d\n", model_index);
479*e01b6f76SAndroid Build Coastguard Worker ALOGI("Model Index: %d", model_index);
480*e01b6f76SAndroid Build Coastguard Worker write_vastr(conn_socket, "Model handle: %d\n", last_model_context->model_handle);
481*e01b6f76SAndroid Build Coastguard Worker ALOGI("Model handle: %d", last_model_context->model_handle);
482*e01b6f76SAndroid Build Coastguard Worker write_uuid(conn_socket, last_model_context->model_uuid);
483*e01b6f76SAndroid Build Coastguard Worker print_uuid(last_model_context->model_uuid);
484*e01b6f76SAndroid Build Coastguard Worker sound_trigger_sound_model_type_t model_type = last_model_context->model_type;
485*e01b6f76SAndroid Build Coastguard Worker
486*e01b6f76SAndroid Build Coastguard Worker if (model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
487*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "Keyphrase sound Model.\n");
488*e01b6f76SAndroid Build Coastguard Worker ALOGI("Keyphrase sound Model.");
489*e01b6f76SAndroid Build Coastguard Worker } else if (model_type == SOUND_MODEL_TYPE_GENERIC) {
490*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "Generic sound Model.\n");
491*e01b6f76SAndroid Build Coastguard Worker ALOGI("Generic sound Model.");
492*e01b6f76SAndroid Build Coastguard Worker } else {
493*e01b6f76SAndroid Build Coastguard Worker write_vastr(conn_socket, "Unknown sound model type: %d\n", model_type);
494*e01b6f76SAndroid Build Coastguard Worker ALOGI("Unknown sound model type: %d", model_type);
495*e01b6f76SAndroid Build Coastguard Worker }
496*e01b6f76SAndroid Build Coastguard Worker if (last_model_context->model_started) {
497*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "Model started.\n");
498*e01b6f76SAndroid Build Coastguard Worker ALOGI("Model started.\n");
499*e01b6f76SAndroid Build Coastguard Worker } else {
500*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "Model stopped.\n");
501*e01b6f76SAndroid Build Coastguard Worker ALOGI("Model stopped.\n");
502*e01b6f76SAndroid Build Coastguard Worker }
503*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "-----------------------\n\n");
504*e01b6f76SAndroid Build Coastguard Worker ALOGI("----\n\n");
505*e01b6f76SAndroid Build Coastguard Worker last_model_context = last_model_context->next;
506*e01b6f76SAndroid Build Coastguard Worker model_index++;
507*e01b6f76SAndroid Build Coastguard Worker }
508*e01b6f76SAndroid Build Coastguard Worker }
509*e01b6f76SAndroid Build Coastguard Worker
510*e01b6f76SAndroid Build Coastguard Worker // Gets the next word from buffer, replaces '\n' or ' ' with '\0'.
get_command(char * buffer)511*e01b6f76SAndroid Build Coastguard Worker char* get_command(char* buffer) {
512*e01b6f76SAndroid Build Coastguard Worker char* command = strtok(buffer, " ");
513*e01b6f76SAndroid Build Coastguard Worker char* newline = strchr(command, '\n');
514*e01b6f76SAndroid Build Coastguard Worker if (newline != NULL) {
515*e01b6f76SAndroid Build Coastguard Worker *newline = '\0';
516*e01b6f76SAndroid Build Coastguard Worker }
517*e01b6f76SAndroid Build Coastguard Worker return command;
518*e01b6f76SAndroid Build Coastguard Worker }
519*e01b6f76SAndroid Build Coastguard Worker
520*e01b6f76SAndroid Build Coastguard Worker // Parses data coming in from the local socket, executes commands. Returns when
521*e01b6f76SAndroid Build Coastguard Worker // done. Return code indicates whether the server should continue listening or
522*e01b6f76SAndroid Build Coastguard Worker // abort (true if continue listening).
parse_socket_data(int conn_socket,struct stub_sound_trigger_device * stdev)523*e01b6f76SAndroid Build Coastguard Worker bool parse_socket_data(int conn_socket, struct stub_sound_trigger_device* stdev) {
524*e01b6f76SAndroid Build Coastguard Worker ALOGI("Calling parse_socket_data");
525*e01b6f76SAndroid Build Coastguard Worker bool input_done = false;
526*e01b6f76SAndroid Build Coastguard Worker char buffer[PARSE_BUF_LEN];
527*e01b6f76SAndroid Build Coastguard Worker FILE* input_fp = fdopen(conn_socket, "r");
528*e01b6f76SAndroid Build Coastguard Worker bool continue_listening = true;
529*e01b6f76SAndroid Build Coastguard Worker
530*e01b6f76SAndroid Build Coastguard Worker // Note: Since we acquire a lock inside this loop, do not use break or other
531*e01b6f76SAndroid Build Coastguard Worker // exit methods without releasing this lock.
532*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "\n>>> ");
533*e01b6f76SAndroid Build Coastguard Worker while(!input_done) {
534*e01b6f76SAndroid Build Coastguard Worker if (fgets(buffer, PARSE_BUF_LEN, input_fp) != NULL) {
535*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_lock(&stdev->lock);
536*e01b6f76SAndroid Build Coastguard Worker char* command = strtok(buffer, " \r\n");
537*e01b6f76SAndroid Build Coastguard Worker if (command == NULL) {
538*e01b6f76SAndroid Build Coastguard Worker write_bad_command_error(conn_socket, command);
539*e01b6f76SAndroid Build Coastguard Worker } else if (strncmp(command, COMMAND_LS, 2) == 0) {
540*e01b6f76SAndroid Build Coastguard Worker list_models(conn_socket, buffer, stdev);
541*e01b6f76SAndroid Build Coastguard Worker } else if (strcmp(command, COMMAND_RECOGNITION_TRIGGER) == 0) {
542*e01b6f76SAndroid Build Coastguard Worker send_event(conn_socket, stdev, EVENT_RECOGNITION, RECOGNITION_STATUS_SUCCESS);
543*e01b6f76SAndroid Build Coastguard Worker } else if (strcmp(command, COMMAND_RECOGNITION_ABORT) == 0) {
544*e01b6f76SAndroid Build Coastguard Worker send_event(conn_socket, stdev, EVENT_RECOGNITION, RECOGNITION_STATUS_ABORT);
545*e01b6f76SAndroid Build Coastguard Worker } else if (strcmp(command, COMMAND_RECOGNITION_FAILURE) == 0) {
546*e01b6f76SAndroid Build Coastguard Worker send_event(conn_socket, stdev, EVENT_RECOGNITION, RECOGNITION_STATUS_FAILURE);
547*e01b6f76SAndroid Build Coastguard Worker } else if (strcmp(command, COMMAND_UPDATE) == 0) {
548*e01b6f76SAndroid Build Coastguard Worker send_event(conn_socket, stdev, EVENT_SOUND_MODEL, SOUND_MODEL_STATUS_UPDATED);
549*e01b6f76SAndroid Build Coastguard Worker } else if (strncmp(command, COMMAND_CLEAR, 5) == 0) {
550*e01b6f76SAndroid Build Coastguard Worker unload_all_sound_models(stdev);
551*e01b6f76SAndroid Build Coastguard Worker } else if (strncmp(command, COMMAND_CLOSE, 5) == 0) {
552*e01b6f76SAndroid Build Coastguard Worker ALOGI("Closing this connection.");
553*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "Closing this connection.");
554*e01b6f76SAndroid Build Coastguard Worker input_done = true;
555*e01b6f76SAndroid Build Coastguard Worker } else if (strncmp(command, COMMAND_END, 3) == 0) {
556*e01b6f76SAndroid Build Coastguard Worker ALOGI("End command received.");
557*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "End command received. Stopping connection.");
558*e01b6f76SAndroid Build Coastguard Worker continue_listening = false;
559*e01b6f76SAndroid Build Coastguard Worker input_done = true;
560*e01b6f76SAndroid Build Coastguard Worker } else {
561*e01b6f76SAndroid Build Coastguard Worker write_vastr(conn_socket, "\nBad command %s.\n\n", command);
562*e01b6f76SAndroid Build Coastguard Worker }
563*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
564*e01b6f76SAndroid Build Coastguard Worker } else {
565*e01b6f76SAndroid Build Coastguard Worker ALOGI("parse_socket_data done (got null)");
566*e01b6f76SAndroid Build Coastguard Worker input_done = true; // break.
567*e01b6f76SAndroid Build Coastguard Worker }
568*e01b6f76SAndroid Build Coastguard Worker write_string(conn_socket, "\n>>> ");
569*e01b6f76SAndroid Build Coastguard Worker }
570*e01b6f76SAndroid Build Coastguard Worker return continue_listening;
571*e01b6f76SAndroid Build Coastguard Worker }
572*e01b6f76SAndroid Build Coastguard Worker
send_loop_kill_signal()573*e01b6f76SAndroid Build Coastguard Worker static void send_loop_kill_signal() {
574*e01b6f76SAndroid Build Coastguard Worker ALOGI("Sending loop thread kill signal");
575*e01b6f76SAndroid Build Coastguard Worker int self_socket = socket(AF_INET, SOCK_STREAM, 0);
576*e01b6f76SAndroid Build Coastguard Worker struct sockaddr_in remote_info;
577*e01b6f76SAndroid Build Coastguard Worker memset(&remote_info, 0, sizeof(remote_info));
578*e01b6f76SAndroid Build Coastguard Worker remote_info.sin_family = AF_INET;
579*e01b6f76SAndroid Build Coastguard Worker remote_info.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
580*e01b6f76SAndroid Build Coastguard Worker remote_info.sin_port = htons(14035);
581*e01b6f76SAndroid Build Coastguard Worker if (connect(self_socket, (struct sockaddr *)&remote_info, sizeof(struct sockaddr)) == 0) {
582*e01b6f76SAndroid Build Coastguard Worker send(self_socket, COMMAND_END, 3, 0);
583*e01b6f76SAndroid Build Coastguard Worker } else {
584*e01b6f76SAndroid Build Coastguard Worker ALOGI("Could not connect");
585*e01b6f76SAndroid Build Coastguard Worker }
586*e01b6f76SAndroid Build Coastguard Worker close(self_socket);
587*e01b6f76SAndroid Build Coastguard Worker ALOGI("Sent loop thread kill signal");
588*e01b6f76SAndroid Build Coastguard Worker }
589*e01b6f76SAndroid Build Coastguard Worker
stdev_get_properties(const struct sound_trigger_hw_device * dev,struct sound_trigger_properties * properties)590*e01b6f76SAndroid Build Coastguard Worker static int stdev_get_properties(const struct sound_trigger_hw_device *dev,
591*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_properties *properties) {
592*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
593*e01b6f76SAndroid Build Coastguard Worker
594*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
595*e01b6f76SAndroid Build Coastguard Worker if (properties == NULL)
596*e01b6f76SAndroid Build Coastguard Worker return -EINVAL;
597*e01b6f76SAndroid Build Coastguard Worker memcpy(properties, &hw_properties, sizeof(struct sound_trigger_properties));
598*e01b6f76SAndroid Build Coastguard Worker return 0;
599*e01b6f76SAndroid Build Coastguard Worker }
600*e01b6f76SAndroid Build Coastguard Worker
stdev_load_sound_model(const struct sound_trigger_hw_device * dev,struct sound_trigger_sound_model * sound_model,sound_model_callback_t callback,void * cookie,sound_model_handle_t * handle)601*e01b6f76SAndroid Build Coastguard Worker static int stdev_load_sound_model(const struct sound_trigger_hw_device *dev,
602*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_sound_model *sound_model,
603*e01b6f76SAndroid Build Coastguard Worker sound_model_callback_t callback,
604*e01b6f76SAndroid Build Coastguard Worker void *cookie,
605*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t *handle) {
606*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
607*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s stdev %p", __func__, stdev);
608*e01b6f76SAndroid Build Coastguard Worker int status = 0;
609*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_lock(&stdev->lock);
610*e01b6f76SAndroid Build Coastguard Worker
611*e01b6f76SAndroid Build Coastguard Worker if (handle == NULL || sound_model == NULL) {
612*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
613*e01b6f76SAndroid Build Coastguard Worker return -EINVAL;
614*e01b6f76SAndroid Build Coastguard Worker }
615*e01b6f76SAndroid Build Coastguard Worker if (sound_model->data_size == 0 ||
616*e01b6f76SAndroid Build Coastguard Worker sound_model->data_offset < sizeof(struct sound_trigger_sound_model)) {
617*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
618*e01b6f76SAndroid Build Coastguard Worker return -EINVAL;
619*e01b6f76SAndroid Build Coastguard Worker }
620*e01b6f76SAndroid Build Coastguard Worker
621*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context;
622*e01b6f76SAndroid Build Coastguard Worker model_context = malloc(sizeof(struct recognition_context));
623*e01b6f76SAndroid Build Coastguard Worker if(!model_context) {
624*e01b6f76SAndroid Build Coastguard Worker ALOGW("Could not allocate recognition_context");
625*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
626*e01b6f76SAndroid Build Coastguard Worker return -ENOSYS;
627*e01b6f76SAndroid Build Coastguard Worker }
628*e01b6f76SAndroid Build Coastguard Worker
629*e01b6f76SAndroid Build Coastguard Worker // Add the new model context to the recognition_context linked list
630*e01b6f76SAndroid Build Coastguard Worker if (stdev->root_model_context) {
631*e01b6f76SAndroid Build Coastguard Worker // Find the tail
632*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *current_model_context = stdev->root_model_context;
633*e01b6f76SAndroid Build Coastguard Worker unsigned int model_count = 0;
634*e01b6f76SAndroid Build Coastguard Worker while(current_model_context->next) {
635*e01b6f76SAndroid Build Coastguard Worker current_model_context = current_model_context->next;
636*e01b6f76SAndroid Build Coastguard Worker model_count++;
637*e01b6f76SAndroid Build Coastguard Worker if (model_count >= hw_properties.max_sound_models) {
638*e01b6f76SAndroid Build Coastguard Worker ALOGW("Can't load model: reached max sound model limit");
639*e01b6f76SAndroid Build Coastguard Worker free(model_context);
640*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
641*e01b6f76SAndroid Build Coastguard Worker return -ENOSYS;
642*e01b6f76SAndroid Build Coastguard Worker }
643*e01b6f76SAndroid Build Coastguard Worker }
644*e01b6f76SAndroid Build Coastguard Worker current_model_context->next = model_context;
645*e01b6f76SAndroid Build Coastguard Worker } else {
646*e01b6f76SAndroid Build Coastguard Worker stdev->root_model_context = model_context;
647*e01b6f76SAndroid Build Coastguard Worker }
648*e01b6f76SAndroid Build Coastguard Worker
649*e01b6f76SAndroid Build Coastguard Worker model_context->model_handle = generate_sound_model_handle(dev);
650*e01b6f76SAndroid Build Coastguard Worker *handle = model_context->model_handle;
651*e01b6f76SAndroid Build Coastguard Worker model_context->model_type = sound_model->type;
652*e01b6f76SAndroid Build Coastguard Worker
653*e01b6f76SAndroid Build Coastguard Worker char *data = (char *)sound_model + sound_model->data_offset;
654*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s data size %d data %d - %d", __func__,
655*e01b6f76SAndroid Build Coastguard Worker sound_model->data_size, data[0], data[sound_model->data_size - 1]);
656*e01b6f76SAndroid Build Coastguard Worker model_context->model_uuid = sound_model->uuid;
657*e01b6f76SAndroid Build Coastguard Worker model_context->model_callback = callback;
658*e01b6f76SAndroid Build Coastguard Worker model_context->model_cookie = cookie;
659*e01b6f76SAndroid Build Coastguard Worker model_context->config = NULL;
660*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_callback = NULL;
661*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_cookie = NULL;
662*e01b6f76SAndroid Build Coastguard Worker model_context->next = NULL;
663*e01b6f76SAndroid Build Coastguard Worker model_context->model_started = false;
664*e01b6f76SAndroid Build Coastguard Worker ALOGI("Sound model loaded: Handle %d ", *handle);
665*e01b6f76SAndroid Build Coastguard Worker
666*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
667*e01b6f76SAndroid Build Coastguard Worker return status;
668*e01b6f76SAndroid Build Coastguard Worker }
669*e01b6f76SAndroid Build Coastguard Worker
unload_all_sound_models(struct stub_sound_trigger_device * stdev)670*e01b6f76SAndroid Build Coastguard Worker static void unload_all_sound_models(struct stub_sound_trigger_device *stdev) {
671*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
672*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = stdev->root_model_context;
673*e01b6f76SAndroid Build Coastguard Worker stdev->root_model_context = NULL;
674*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_lock(&stdev->lock);
675*e01b6f76SAndroid Build Coastguard Worker while (model_context) {
676*e01b6f76SAndroid Build Coastguard Worker ALOGI("Deleting model with handle: %d", model_context->model_handle);
677*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *temp = model_context;
678*e01b6f76SAndroid Build Coastguard Worker model_context = model_context->next;
679*e01b6f76SAndroid Build Coastguard Worker free(temp->config);
680*e01b6f76SAndroid Build Coastguard Worker free(temp);
681*e01b6f76SAndroid Build Coastguard Worker }
682*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
683*e01b6f76SAndroid Build Coastguard Worker }
684*e01b6f76SAndroid Build Coastguard Worker
stdev_unload_sound_model(const struct sound_trigger_hw_device * dev,sound_model_handle_t handle)685*e01b6f76SAndroid Build Coastguard Worker static int stdev_unload_sound_model(const struct sound_trigger_hw_device *dev,
686*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t handle) {
687*e01b6f76SAndroid Build Coastguard Worker // If recognizing, stop_recognition must be called for a sound model before unload_sound_model
688*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
689*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
690*e01b6f76SAndroid Build Coastguard Worker int status = 0;
691*e01b6f76SAndroid Build Coastguard Worker ALOGI("unload_sound_model:%d", handle);
692*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_lock(&stdev->lock);
693*e01b6f76SAndroid Build Coastguard Worker
694*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = NULL;
695*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *previous_model_context = NULL;
696*e01b6f76SAndroid Build Coastguard Worker if (stdev->root_model_context) {
697*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *current_model_context = stdev->root_model_context;
698*e01b6f76SAndroid Build Coastguard Worker while(current_model_context) {
699*e01b6f76SAndroid Build Coastguard Worker if (current_model_context->model_handle == handle) {
700*e01b6f76SAndroid Build Coastguard Worker model_context = current_model_context;
701*e01b6f76SAndroid Build Coastguard Worker break;
702*e01b6f76SAndroid Build Coastguard Worker }
703*e01b6f76SAndroid Build Coastguard Worker previous_model_context = current_model_context;
704*e01b6f76SAndroid Build Coastguard Worker current_model_context = current_model_context->next;
705*e01b6f76SAndroid Build Coastguard Worker }
706*e01b6f76SAndroid Build Coastguard Worker }
707*e01b6f76SAndroid Build Coastguard Worker if (!model_context) {
708*e01b6f76SAndroid Build Coastguard Worker ALOGW("Can't find sound model handle %d in registered list", handle);
709*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
710*e01b6f76SAndroid Build Coastguard Worker return -ENOSYS;
711*e01b6f76SAndroid Build Coastguard Worker }
712*e01b6f76SAndroid Build Coastguard Worker if (previous_model_context) {
713*e01b6f76SAndroid Build Coastguard Worker previous_model_context->next = model_context->next;
714*e01b6f76SAndroid Build Coastguard Worker } else {
715*e01b6f76SAndroid Build Coastguard Worker stdev->root_model_context = model_context->next;
716*e01b6f76SAndroid Build Coastguard Worker }
717*e01b6f76SAndroid Build Coastguard Worker free(model_context->config);
718*e01b6f76SAndroid Build Coastguard Worker free(model_context);
719*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
720*e01b6f76SAndroid Build Coastguard Worker return status;
721*e01b6f76SAndroid Build Coastguard Worker }
722*e01b6f76SAndroid Build Coastguard Worker
stdev_start_recognition(const struct sound_trigger_hw_device * dev,sound_model_handle_t handle,const struct sound_trigger_recognition_config * config,recognition_callback_t callback,void * cookie)723*e01b6f76SAndroid Build Coastguard Worker static int stdev_start_recognition(const struct sound_trigger_hw_device *dev,
724*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t handle,
725*e01b6f76SAndroid Build Coastguard Worker const struct sound_trigger_recognition_config *config,
726*e01b6f76SAndroid Build Coastguard Worker recognition_callback_t callback,
727*e01b6f76SAndroid Build Coastguard Worker void *cookie) {
728*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
729*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
730*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_lock(&stdev->lock);
731*e01b6f76SAndroid Build Coastguard Worker
732*e01b6f76SAndroid Build Coastguard Worker /* If other models running with callbacks, don't start trigger thread */
733*e01b6f76SAndroid Build Coastguard Worker bool other_callbacks_found = recognition_callback_exists(stdev);
734*e01b6f76SAndroid Build Coastguard Worker
735*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = get_model_context(stdev, handle);
736*e01b6f76SAndroid Build Coastguard Worker if (!model_context) {
737*e01b6f76SAndroid Build Coastguard Worker ALOGW("Can't find sound model handle %d in registered list", handle);
738*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
739*e01b6f76SAndroid Build Coastguard Worker return -ENOSYS;
740*e01b6f76SAndroid Build Coastguard Worker }
741*e01b6f76SAndroid Build Coastguard Worker
742*e01b6f76SAndroid Build Coastguard Worker free(model_context->config);
743*e01b6f76SAndroid Build Coastguard Worker model_context->config = NULL;
744*e01b6f76SAndroid Build Coastguard Worker if (config) {
745*e01b6f76SAndroid Build Coastguard Worker model_context->config = malloc(sizeof(*config));
746*e01b6f76SAndroid Build Coastguard Worker if (!model_context->config) {
747*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
748*e01b6f76SAndroid Build Coastguard Worker return -ENOMEM;
749*e01b6f76SAndroid Build Coastguard Worker }
750*e01b6f76SAndroid Build Coastguard Worker memcpy(model_context->config, config, sizeof(*config));
751*e01b6f76SAndroid Build Coastguard Worker }
752*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_callback = callback;
753*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_cookie = cookie;
754*e01b6f76SAndroid Build Coastguard Worker model_context->model_started = true;
755*e01b6f76SAndroid Build Coastguard Worker
756*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
757*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s done for handle %d", __func__, handle);
758*e01b6f76SAndroid Build Coastguard Worker return 0;
759*e01b6f76SAndroid Build Coastguard Worker }
760*e01b6f76SAndroid Build Coastguard Worker
stdev_stop_recognition(const struct sound_trigger_hw_device * dev,sound_model_handle_t handle)761*e01b6f76SAndroid Build Coastguard Worker static int stdev_stop_recognition(const struct sound_trigger_hw_device *dev,
762*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t handle) {
763*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
764*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
765*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_lock(&stdev->lock);
766*e01b6f76SAndroid Build Coastguard Worker
767*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = get_model_context(stdev, handle);
768*e01b6f76SAndroid Build Coastguard Worker if (!model_context) {
769*e01b6f76SAndroid Build Coastguard Worker ALOGW("Can't find sound model handle %d in registered list", handle);
770*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
771*e01b6f76SAndroid Build Coastguard Worker return -ENOSYS;
772*e01b6f76SAndroid Build Coastguard Worker }
773*e01b6f76SAndroid Build Coastguard Worker
774*e01b6f76SAndroid Build Coastguard Worker free(model_context->config);
775*e01b6f76SAndroid Build Coastguard Worker model_context->config = NULL;
776*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_callback = NULL;
777*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_cookie = NULL;
778*e01b6f76SAndroid Build Coastguard Worker model_context->model_started = false;
779*e01b6f76SAndroid Build Coastguard Worker
780*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
781*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s done for handle %d", __func__, handle);
782*e01b6f76SAndroid Build Coastguard Worker
783*e01b6f76SAndroid Build Coastguard Worker return 0;
784*e01b6f76SAndroid Build Coastguard Worker }
785*e01b6f76SAndroid Build Coastguard Worker
stdev_stop_all_recognitions(const struct sound_trigger_hw_device * dev)786*e01b6f76SAndroid Build Coastguard Worker static int stdev_stop_all_recognitions(const struct sound_trigger_hw_device *dev) {
787*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
788*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
789*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_lock(&stdev->lock);
790*e01b6f76SAndroid Build Coastguard Worker
791*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = stdev->root_model_context;
792*e01b6f76SAndroid Build Coastguard Worker while (model_context) {
793*e01b6f76SAndroid Build Coastguard Worker free(model_context->config);
794*e01b6f76SAndroid Build Coastguard Worker model_context->config = NULL;
795*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_callback = NULL;
796*e01b6f76SAndroid Build Coastguard Worker model_context->recognition_cookie = NULL;
797*e01b6f76SAndroid Build Coastguard Worker model_context->model_started = false;
798*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s stopped handle %d", __func__, model_context->model_handle);
799*e01b6f76SAndroid Build Coastguard Worker
800*e01b6f76SAndroid Build Coastguard Worker model_context = model_context->next;
801*e01b6f76SAndroid Build Coastguard Worker }
802*e01b6f76SAndroid Build Coastguard Worker
803*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
804*e01b6f76SAndroid Build Coastguard Worker
805*e01b6f76SAndroid Build Coastguard Worker return 0;
806*e01b6f76SAndroid Build Coastguard Worker }
807*e01b6f76SAndroid Build Coastguard Worker
stdev_get_model_state(const struct sound_trigger_hw_device * dev,sound_model_handle_t handle)808*e01b6f76SAndroid Build Coastguard Worker static int stdev_get_model_state(const struct sound_trigger_hw_device *dev,
809*e01b6f76SAndroid Build Coastguard Worker sound_model_handle_t handle) {
810*e01b6f76SAndroid Build Coastguard Worker int ret = 0;
811*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
812*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s", __func__);
813*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_lock(&stdev->lock);
814*e01b6f76SAndroid Build Coastguard Worker
815*e01b6f76SAndroid Build Coastguard Worker struct recognition_context *model_context = get_model_context(stdev, handle);
816*e01b6f76SAndroid Build Coastguard Worker if (!model_context) {
817*e01b6f76SAndroid Build Coastguard Worker ALOGW("Can't find sound model handle %d in registered list", handle);
818*e01b6f76SAndroid Build Coastguard Worker ret = -ENOSYS;
819*e01b6f76SAndroid Build Coastguard Worker goto exit;
820*e01b6f76SAndroid Build Coastguard Worker }
821*e01b6f76SAndroid Build Coastguard Worker
822*e01b6f76SAndroid Build Coastguard Worker if (!model_context->model_started) {
823*e01b6f76SAndroid Build Coastguard Worker ALOGW("Sound model %d not started", handle);
824*e01b6f76SAndroid Build Coastguard Worker ret = -ENOSYS;
825*e01b6f76SAndroid Build Coastguard Worker goto exit;
826*e01b6f76SAndroid Build Coastguard Worker }
827*e01b6f76SAndroid Build Coastguard Worker
828*e01b6f76SAndroid Build Coastguard Worker if (model_context->recognition_callback == NULL) {
829*e01b6f76SAndroid Build Coastguard Worker ALOGW("Sound model %d not initialized", handle);
830*e01b6f76SAndroid Build Coastguard Worker ret = -ENOSYS;
831*e01b6f76SAndroid Build Coastguard Worker goto exit;
832*e01b6f76SAndroid Build Coastguard Worker }
833*e01b6f76SAndroid Build Coastguard Worker
834*e01b6f76SAndroid Build Coastguard Worker // TODO(mdooley): trigger recognition event
835*e01b6f76SAndroid Build Coastguard Worker
836*e01b6f76SAndroid Build Coastguard Worker exit:
837*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_unlock(&stdev->lock);
838*e01b6f76SAndroid Build Coastguard Worker ALOGI("%s done for handle %d", __func__, handle);
839*e01b6f76SAndroid Build Coastguard Worker
840*e01b6f76SAndroid Build Coastguard Worker return ret;
841*e01b6f76SAndroid Build Coastguard Worker }
842*e01b6f76SAndroid Build Coastguard Worker
843*e01b6f76SAndroid Build Coastguard Worker __attribute__ ((visibility ("default")))
sound_trigger_open_for_streaming()844*e01b6f76SAndroid Build Coastguard Worker int sound_trigger_open_for_streaming() {
845*e01b6f76SAndroid Build Coastguard Worker int ret = 0;
846*e01b6f76SAndroid Build Coastguard Worker return ret;
847*e01b6f76SAndroid Build Coastguard Worker }
848*e01b6f76SAndroid Build Coastguard Worker
849*e01b6f76SAndroid Build Coastguard Worker __attribute__ ((visibility ("default")))
sound_trigger_read_samples(int audio_handle,void * buffer,size_t buffer_len)850*e01b6f76SAndroid Build Coastguard Worker size_t sound_trigger_read_samples(int audio_handle, void *buffer, size_t buffer_len) {
851*e01b6f76SAndroid Build Coastguard Worker size_t ret = 0;
852*e01b6f76SAndroid Build Coastguard Worker return ret;
853*e01b6f76SAndroid Build Coastguard Worker }
854*e01b6f76SAndroid Build Coastguard Worker
855*e01b6f76SAndroid Build Coastguard Worker __attribute__ ((visibility ("default")))
sound_trigger_close_for_streaming(int audio_handle __unused)856*e01b6f76SAndroid Build Coastguard Worker int sound_trigger_close_for_streaming(int audio_handle __unused) {
857*e01b6f76SAndroid Build Coastguard Worker return 0;
858*e01b6f76SAndroid Build Coastguard Worker }
859*e01b6f76SAndroid Build Coastguard Worker
stdev_close(hw_device_t * device)860*e01b6f76SAndroid Build Coastguard Worker static int stdev_close(hw_device_t *device) {
861*e01b6f76SAndroid Build Coastguard Worker // TODO: Implement the ability to stop the control thread. Since this is a
862*e01b6f76SAndroid Build Coastguard Worker // test hal, we have skipped implementing this for now. A possible method
863*e01b6f76SAndroid Build Coastguard Worker // would register a signal handler for the control thread so that any
864*e01b6f76SAndroid Build Coastguard Worker // blocking socket calls can be interrupted. We would send that signal here
865*e01b6f76SAndroid Build Coastguard Worker // to interrupt and quit the thread.
866*e01b6f76SAndroid Build Coastguard Worker free(device);
867*e01b6f76SAndroid Build Coastguard Worker return 0;
868*e01b6f76SAndroid Build Coastguard Worker }
869*e01b6f76SAndroid Build Coastguard Worker
stdev_open(const hw_module_t * module,const char * name,hw_device_t ** device)870*e01b6f76SAndroid Build Coastguard Worker static int stdev_open(const hw_module_t* module, const char* name,
871*e01b6f76SAndroid Build Coastguard Worker hw_device_t** device) {
872*e01b6f76SAndroid Build Coastguard Worker struct stub_sound_trigger_device *stdev;
873*e01b6f76SAndroid Build Coastguard Worker int ret;
874*e01b6f76SAndroid Build Coastguard Worker
875*e01b6f76SAndroid Build Coastguard Worker if (strcmp(name, SOUND_TRIGGER_HARDWARE_INTERFACE) != 0)
876*e01b6f76SAndroid Build Coastguard Worker return -EINVAL;
877*e01b6f76SAndroid Build Coastguard Worker
878*e01b6f76SAndroid Build Coastguard Worker stdev = calloc(1, sizeof(struct stub_sound_trigger_device));
879*e01b6f76SAndroid Build Coastguard Worker if (!stdev)
880*e01b6f76SAndroid Build Coastguard Worker return -ENOMEM;
881*e01b6f76SAndroid Build Coastguard Worker
882*e01b6f76SAndroid Build Coastguard Worker stdev->next_sound_model_id = 1;
883*e01b6f76SAndroid Build Coastguard Worker stdev->root_model_context = NULL;
884*e01b6f76SAndroid Build Coastguard Worker
885*e01b6f76SAndroid Build Coastguard Worker stdev->device.common.tag = HARDWARE_DEVICE_TAG;
886*e01b6f76SAndroid Build Coastguard Worker stdev->device.common.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_1;
887*e01b6f76SAndroid Build Coastguard Worker stdev->device.common.module = (struct hw_module_t *) module;
888*e01b6f76SAndroid Build Coastguard Worker stdev->device.common.close = stdev_close;
889*e01b6f76SAndroid Build Coastguard Worker stdev->device.get_properties = stdev_get_properties;
890*e01b6f76SAndroid Build Coastguard Worker stdev->device.load_sound_model = stdev_load_sound_model;
891*e01b6f76SAndroid Build Coastguard Worker stdev->device.unload_sound_model = stdev_unload_sound_model;
892*e01b6f76SAndroid Build Coastguard Worker stdev->device.start_recognition = stdev_start_recognition;
893*e01b6f76SAndroid Build Coastguard Worker stdev->device.stop_recognition = stdev_stop_recognition;
894*e01b6f76SAndroid Build Coastguard Worker stdev->device.stop_all_recognitions = stdev_stop_all_recognitions;
895*e01b6f76SAndroid Build Coastguard Worker stdev->device.get_model_state = stdev_get_model_state;
896*e01b6f76SAndroid Build Coastguard Worker
897*e01b6f76SAndroid Build Coastguard Worker pthread_mutex_init(&stdev->lock, (const pthread_mutexattr_t *) NULL);
898*e01b6f76SAndroid Build Coastguard Worker
899*e01b6f76SAndroid Build Coastguard Worker *device = &stdev->device.common;
900*e01b6f76SAndroid Build Coastguard Worker
901*e01b6f76SAndroid Build Coastguard Worker pthread_create(&stdev->control_thread, (const pthread_attr_t *) NULL,
902*e01b6f76SAndroid Build Coastguard Worker control_thread_loop, stdev);
903*e01b6f76SAndroid Build Coastguard Worker ALOGI("Starting control thread for the stub hal.");
904*e01b6f76SAndroid Build Coastguard Worker
905*e01b6f76SAndroid Build Coastguard Worker return 0;
906*e01b6f76SAndroid Build Coastguard Worker }
907*e01b6f76SAndroid Build Coastguard Worker
908*e01b6f76SAndroid Build Coastguard Worker static struct hw_module_methods_t hal_module_methods = {
909*e01b6f76SAndroid Build Coastguard Worker .open = stdev_open,
910*e01b6f76SAndroid Build Coastguard Worker };
911*e01b6f76SAndroid Build Coastguard Worker
912*e01b6f76SAndroid Build Coastguard Worker struct sound_trigger_module HAL_MODULE_INFO_SYM = {
913*e01b6f76SAndroid Build Coastguard Worker .common = {
914*e01b6f76SAndroid Build Coastguard Worker .tag = HARDWARE_MODULE_TAG,
915*e01b6f76SAndroid Build Coastguard Worker .module_api_version = SOUND_TRIGGER_MODULE_API_VERSION_1_0,
916*e01b6f76SAndroid Build Coastguard Worker .hal_api_version = HARDWARE_HAL_API_VERSION,
917*e01b6f76SAndroid Build Coastguard Worker .id = SOUND_TRIGGER_HARDWARE_MODULE_ID,
918*e01b6f76SAndroid Build Coastguard Worker .name = "Default sound trigger HAL",
919*e01b6f76SAndroid Build Coastguard Worker .author = "The Android Open Source Project",
920*e01b6f76SAndroid Build Coastguard Worker .methods = &hal_module_methods,
921*e01b6f76SAndroid Build Coastguard Worker },
922*e01b6f76SAndroid Build Coastguard Worker };
923