xref: /aosp_15_r20/hardware/libhardware/modules/soundtrigger/sound_trigger_hw.c (revision e01b6f769022e40d0923dee176e8dc7cd1d52984)
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