blob: 8083b1f5560eebaeab220a02fa970bfae2fbb29d [file] [log] [blame]
Eric Laurentcbca9052014-04-18 17:54:10 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ryan Bavetta4615aad2016-01-27 16:12:04 -080017
18/* This HAL simulates triggers from the DSP.
19 * To send a trigger from the command line you can type:
20 *
21 * adb forward tcp:14035 tcp:14035
22 * echo $'\001' | nc -q -1 localhost 14035
23 *
24 * $'\001' corresponds to the index_position of loaded sound
25 * model, you can also send $'\002' etc. $'\000' is the kill
26 * signal for the trigger listening thread.
27 *
Ryan Bavettabe0c8fd2016-02-01 15:17:12 -080028 * To enable this file, you can make with command line parameter
29 * SOUND_TRIGGER_USE_STUB_MODULE=1
Ryan Bavetta4615aad2016-01-27 16:12:04 -080030 */
31
Eric Laurentcbca9052014-04-18 17:54:10 -070032#define LOG_TAG "sound_trigger_hw_default"
Ryan Bavettacc6541c2016-02-09 21:20:51 -080033#define LOG_NDEBUG 1
Eric Laurentcbca9052014-04-18 17:54:10 -070034
35#include <errno.h>
Ryan Bavetta4615aad2016-01-27 16:12:04 -080036#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40#include <arpa/inet.h>
41#include <sys/types.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44
45#include <errno.h>
Eric Laurentcbca9052014-04-18 17:54:10 -070046#include <pthread.h>
47#include <sys/prctl.h>
48#include <cutils/log.h>
49
50#include <hardware/hardware.h>
51#include <system/sound_trigger.h>
52#include <hardware/sound_trigger.h>
53
54static const struct sound_trigger_properties hw_properties = {
55 "The Android Open Source Project", // implementor
56 "Sound Trigger stub HAL", // description
57 1, // version
58 { 0xed7a7d60, 0xc65e, 0x11e3, 0x9be4, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
Ryan Bavetta4615aad2016-01-27 16:12:04 -080059 2, // max_sound_models
Eric Laurentcbca9052014-04-18 17:54:10 -070060 1, // max_key_phrases
61 1, // max_users
62 RECOGNITION_MODE_VOICE_TRIGGER, // recognition_modes
63 false, // capture_transition
64 0, // max_buffer_ms
65 false, // concurrent_capture
Eric Laurent83cd8302014-07-30 08:58:39 -070066 false, // trigger_in_event
Eric Laurentcbca9052014-04-18 17:54:10 -070067 0 // power_consumption_mw
68};
69
Ryan Bavetta4615aad2016-01-27 16:12:04 -080070struct recognition_context {
Ryan Bavettacc6541c2016-02-09 21:20:51 -080071 // Sound Model information, added in method load_sound_model
72 sound_model_handle_t model_handle;
73 sound_trigger_sound_model_type_t model_type;
74 sound_model_callback_t model_callback;
75 void *model_cookie;
Ryan Bavetta4615aad2016-01-27 16:12:04 -080076
Ryan Bavettacc6541c2016-02-09 21:20:51 -080077 // Sound Model information, added in start_recognition
Ryan Bavetta4615aad2016-01-27 16:12:04 -080078 struct sound_trigger_recognition_config *config;
79 recognition_callback_t recognition_callback;
80 void *recognition_cookie;
Ryan Bavettacc6541c2016-02-09 21:20:51 -080081
82 // Next recognition_context in the linked list
83 struct recognition_context *next;
Ryan Bavettabe0c8fd2016-02-01 15:17:12 -080084};
Ryan Bavetta4615aad2016-01-27 16:12:04 -080085
86struct stub_sound_trigger_device {
87 struct sound_trigger_hw_device device;
Eric Laurentcbca9052014-04-18 17:54:10 -070088 pthread_mutex_t lock;
Ryan Bavetta4615aad2016-01-27 16:12:04 -080089 pthread_t callback_thread;
90
Ryan Bavettacc6541c2016-02-09 21:20:51 -080091 // Recognition contexts are stored as a linked list
92 struct recognition_context *root_model_context;
Ryan Bavetta4615aad2016-01-27 16:12:04 -080093
94 int next_sound_model_id;
Eric Laurentcbca9052014-04-18 17:54:10 -070095};
96
Ryan Bavetta4615aad2016-01-27 16:12:04 -080097/* Will reuse ids when overflow occurs */
98static unsigned int generate_sound_model_id(const struct sound_trigger_hw_device *dev) {
99 struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
100 int new_id = stdev->next_sound_model_id;
101 ++stdev->next_sound_model_id;
102 if (stdev->next_sound_model_id == 0) {
103 stdev->next_sound_model_id = 1;
104 }
105 return new_id;
106}
Eric Laurentcbca9052014-04-18 17:54:10 -0700107
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800108static char *sound_trigger_event_alloc(sound_model_handle_t handle,
109 sound_trigger_sound_model_type_t model_type,
110 struct sound_trigger_recognition_config *config) {
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800111 char *data;
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800112 if (model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
113 struct sound_trigger_phrase_recognition_event *event;
114 data = (char *)calloc(1, sizeof(struct sound_trigger_phrase_recognition_event));
115 if (!data)
116 return NULL;
117 event = (struct sound_trigger_phrase_recognition_event *)data;
118 event->common.status = RECOGNITION_STATUS_SUCCESS;
119 event->common.type = SOUND_MODEL_TYPE_KEYPHRASE;
120 event->common.model = handle;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800121
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800122 if (config) {
123 unsigned int i;
124
125 event->num_phrases = config->num_phrases;
126 if (event->num_phrases > SOUND_TRIGGER_MAX_PHRASES)
127 event->num_phrases = SOUND_TRIGGER_MAX_PHRASES;
128 for (i=0; i < event->num_phrases; i++)
129 memcpy(&event->phrase_extras[i],
130 &config->phrases[i],
131 sizeof(struct sound_trigger_phrase_recognition_extra));
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800132 }
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800133
134 event->num_phrases = 1;
135 event->phrase_extras[0].confidence_level = 100;
136 event->phrase_extras[0].num_levels = 1;
137 event->phrase_extras[0].levels[0].level = 100;
138 event->phrase_extras[0].levels[0].user_id = 0;
139 // Signify that all the data is comming through streaming, not through the buffer.
140 event->common.capture_available = true;
141 event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
142 event->common.audio_config.sample_rate = 16000;
143 event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
144 event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
145 } else if (model_type == SOUND_MODEL_TYPE_GENERIC) {
146 struct sound_trigger_generic_recognition_event *event;
147 data = (char *)calloc(1, sizeof(struct sound_trigger_generic_recognition_event));
148 if (!data)
149 return NULL;
150 event = (struct sound_trigger_generic_recognition_event *)data;
151 event->common.status = RECOGNITION_STATUS_SUCCESS;
152 event->common.type = SOUND_MODEL_TYPE_GENERIC;
153 event->common.model = handle;
154
155 // Signify that all the data is comming through streaming, not through the buffer.
156 event->common.capture_available = true;
157 event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
158 event->common.audio_config.sample_rate = 16000;
159 event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
160 event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
161 } else {
162 ALOGW("No Valid Event Type Known");
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800163 return NULL;
164 }
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800165 return data;
166}
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800167
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800168static void send_recognition_event(sound_model_handle_t model_handle,
169 sound_trigger_sound_model_type_t model_type,
170 recognition_callback_t recognition_callback, void *recognition_cookie,
171 struct sound_trigger_recognition_config *config) {
172 if (recognition_callback == NULL) {
173 ALOGI("%s No matching callback for handle %d", __func__, model_handle);
174 return;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800175 }
176
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800177 if (model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
178 struct sound_trigger_phrase_recognition_event *event;
179 event = (struct sound_trigger_phrase_recognition_event *)
180 sound_trigger_event_alloc(model_handle, model_type, config);
181 if (event) {
182 recognition_callback(&event->common, recognition_cookie);
183 free(event);
184 }
185 } else if (model_type == SOUND_MODEL_TYPE_GENERIC) {
186 struct sound_trigger_generic_recognition_event *event;
187 event = (struct sound_trigger_generic_recognition_event *)
188 sound_trigger_event_alloc(model_handle, model_type, config);
189 if (event) {
190 recognition_callback(&event->common, recognition_cookie);
191 free(event);
192 }
193 } else {
194 ALOGI("Unknown Sound Model Type, No Event to Send");
195 }
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800196}
197
198static void *callback_thread_loop(void *context) {
Eric Laurentcbca9052014-04-18 17:54:10 -0700199 struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)context;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800200 struct sockaddr_in incoming_info;
201 struct sockaddr_in self_info;
202 int self_socket;
203 socklen_t sock_size = sizeof(struct sockaddr_in);
204 memset(&self_info, 0, sizeof(self_info));
205 self_info.sin_family = AF_INET;
206 self_info.sin_addr.s_addr = htonl(INADDR_ANY);
207 self_info.sin_port = htons(14035);
Eric Laurentcbca9052014-04-18 17:54:10 -0700208
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800209 bool exit = false;
210 while(!exit) {
211 int received_count;
212 int requested_count = 1;
213 char buffer[requested_count];
214 ALOGE("Opening socket");
215 self_socket = socket(AF_INET, SOCK_STREAM, 0);
216 if (self_socket < 0) {
217 ALOGE("Error on socket creation");
218 exit = true;
219 } else {
220 ALOGI("Socket created");
221 }
Eric Laurentcbca9052014-04-18 17:54:10 -0700222
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800223 int reuse = 1;
224 if (setsockopt(self_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) {
225 ALOGE("setsockopt(SO_REUSEADDR) failed");
226 }
227
228 int bind_result = bind(self_socket, (struct sockaddr *)&self_info, sizeof(struct sockaddr));
229 if (bind_result < 0) {
230 ALOGE("Error on bind");
231 exit = true;
232 }
233
234 int listen_result = listen(self_socket, 1);
235 if (listen_result < 0) {
236 ALOGE("Error on Listen");
237 exit = true;
238 }
239
240 while(!exit) {
241 int con_socket = accept(self_socket, (struct sockaddr *)&incoming_info, &sock_size);
242 if (!con_socket) {
243 ALOGE("Lost socket, cannot send trigger");
244 break;
245 }
246 ALOGI("Connection from %s", inet_ntoa(incoming_info.sin_addr));
247 received_count = recv(con_socket, buffer, requested_count, 0);
248 unsigned int index = buffer[0] - 1;
249 ALOGI("Received data");
250 pthread_mutex_lock(&stdev->lock);
251 if (received_count > 0) {
252 if (buffer[0] == 0) {
253 ALOGI("Received kill signal: stop listening to incoming server messages");
254 exit = true;
255 } else if (index < hw_properties.max_sound_models) {
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800256 ALOGI("Going to send trigger for model index #%d", index );
257 struct recognition_context *model_context = NULL;
258 struct recognition_context *last_model_context = stdev->root_model_context;
259 int model_index = 0;
260 while(last_model_context) {
261 if (model_index == index) {
262 model_context = last_model_context;
263 break;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800264 }
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800265 last_model_context = last_model_context->next;
266 model_index++;
267 }
268 if (model_context) {
269 send_recognition_event(model_context->model_handle,
270 model_context->model_type,
271 model_context->recognition_callback,
272 model_context->recognition_cookie,
273 model_context->config);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800274 } else {
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800275 ALOGI("Sound Model Does Not Exist at this Index: %d", index);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800276 }
277 } else {
278 ALOGI("Data is not recognized: %d", index);
279 }
280 } else {
281 ALOGI("Received sata is size 0");
282 }
283 pthread_mutex_unlock(&stdev->lock);
284 close(con_socket);
285 }
286 ALOGE("Closing socket");
287 close(self_socket);
Eric Laurentcbca9052014-04-18 17:54:10 -0700288 }
Eric Laurentcbca9052014-04-18 17:54:10 -0700289
290 return NULL;
291}
292
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800293static void send_loop_kill_signal() {
294 ALOGI("Sending loop thread kill signal");
295 int self_socket = socket(AF_INET, SOCK_STREAM, 0);
296 struct sockaddr_in remote_info;
297 memset(&remote_info, 0, sizeof(remote_info));
298 remote_info.sin_family = AF_INET;
299 remote_info.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
300 remote_info.sin_port = htons(14035);
301 if (connect(self_socket, (struct sockaddr *)&remote_info, sizeof(struct sockaddr)) == 0) {
302 char msg[] = {0};
303 send(self_socket, msg, 1, 0);
304 } else {
305 ALOGI("Could not connect");
306 }
307 close(self_socket);
308 ALOGI("Sent loop thread kill signal");
309}
310
Eric Laurentcbca9052014-04-18 17:54:10 -0700311static int stdev_get_properties(const struct sound_trigger_hw_device *dev,
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800312 struct sound_trigger_properties *properties) {
Eric Laurentcbca9052014-04-18 17:54:10 -0700313 struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
314
315 ALOGI("%s", __func__);
316 if (properties == NULL)
317 return -EINVAL;
318 memcpy(properties, &hw_properties, sizeof(struct sound_trigger_properties));
319 return 0;
320}
321
322static int stdev_load_sound_model(const struct sound_trigger_hw_device *dev,
323 struct sound_trigger_sound_model *sound_model,
324 sound_model_callback_t callback,
325 void *cookie,
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800326 sound_model_handle_t *handle) {
Eric Laurentcbca9052014-04-18 17:54:10 -0700327 struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
328 int status = 0;
329
330 ALOGI("%s stdev %p", __func__, stdev);
331 pthread_mutex_lock(&stdev->lock);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800332
Eric Laurentcbca9052014-04-18 17:54:10 -0700333 if (handle == NULL || sound_model == NULL) {
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800334 pthread_mutex_unlock(&stdev->lock);
335 return -EINVAL;
Eric Laurentcbca9052014-04-18 17:54:10 -0700336 }
337 if (sound_model->data_size == 0 ||
338 sound_model->data_offset < sizeof(struct sound_trigger_sound_model)) {
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800339 pthread_mutex_unlock(&stdev->lock);
340 return -EINVAL;
Eric Laurentcbca9052014-04-18 17:54:10 -0700341 }
342
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800343 struct recognition_context *model_context;
344 model_context = malloc(sizeof(struct recognition_context));
345 if(!model_context) {
346 ALOGW("Could not allocate recognition_context");
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800347 pthread_mutex_unlock(&stdev->lock);
348 return -ENOSYS;
349 }
350
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800351 // Add the new model context to the recognition_context linked list
352 if (stdev->root_model_context) {
353 // Find the tail
354 struct recognition_context *last_model_context = stdev->root_model_context;
355 int model_count = 0;
356 while(last_model_context->next) {
357 last_model_context = last_model_context->next;
358 model_count++;
359 if (model_count >= hw_properties.max_sound_models) {
360 ALOGW("Can't load model: reached max sound model limit");
361 free(model_context);
362 pthread_mutex_unlock(&stdev->lock);
363 return -ENOSYS;
364 }
365 }
366 last_model_context->next = model_context;
367 } else {
368 stdev->root_model_context = model_context;
369 }
370
371 model_context->model_handle = generate_sound_model_id(dev);
372 *handle = model_context->model_handle;
373 model_context->model_type = sound_model->type;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800374
Eric Laurentcbca9052014-04-18 17:54:10 -0700375 char *data = (char *)sound_model + sound_model->data_offset;
376 ALOGI("%s data size %d data %d - %d", __func__,
377 sound_model->data_size, data[0], data[sound_model->data_size - 1]);
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800378 model_context->model_callback = callback;
379 model_context->model_cookie = cookie;
380 model_context->config = NULL;
381 model_context->recognition_callback = NULL;
382 model_context->recognition_cookie = NULL;
Eric Laurentcbca9052014-04-18 17:54:10 -0700383
Eric Laurentcbca9052014-04-18 17:54:10 -0700384 pthread_mutex_unlock(&stdev->lock);
385 return status;
386}
387
388static int stdev_unload_sound_model(const struct sound_trigger_hw_device *dev,
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800389 sound_model_handle_t handle) {
Eric Laurentcbca9052014-04-18 17:54:10 -0700390 struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
391 int status = 0;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800392 ALOGI("unload_sound_model");
Eric Laurentcbca9052014-04-18 17:54:10 -0700393 pthread_mutex_lock(&stdev->lock);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800394
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800395
396 struct recognition_context *model_context = NULL;
397 struct recognition_context *previous_model_context = NULL;
398 if (stdev->root_model_context) {
399 struct recognition_context *last_model_context = stdev->root_model_context;
400 while(last_model_context) {
401 if (last_model_context->model_handle == handle) {
402 model_context = last_model_context;
403 break;
404 }
405 previous_model_context = last_model_context;
406 last_model_context = last_model_context->next;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800407 }
Eric Laurentcbca9052014-04-18 17:54:10 -0700408 }
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800409 if (!model_context) {
410 ALOGW("Can't find sound model handle %d in registered list", handle);
Eric Laurentcbca9052014-04-18 17:54:10 -0700411 pthread_mutex_unlock(&stdev->lock);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800412 return -ENOSYS;
Eric Laurentcbca9052014-04-18 17:54:10 -0700413 }
414
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800415 if(previous_model_context) {
416 previous_model_context->next = model_context->next;
417 } else {
418 stdev->root_model_context = model_context->next;
419 }
420 free(model_context->config);
421 free(model_context);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800422
423 /* If no more models running with callbacks, stop trigger thread */
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800424 bool other_callbacks_found = false;
425 if (stdev->root_model_context) {
426 struct recognition_context *last_model_context = stdev->root_model_context;
427 while(last_model_context) {
428 if (last_model_context->recognition_callback != NULL) {
429 other_callbacks_found = true;
430 break;
431 }
432 last_model_context = last_model_context->next;
433 }
434 }
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800435 if (!other_callbacks_found) {
436 send_loop_kill_signal();
437 pthread_mutex_unlock(&stdev->lock);
438 pthread_join(stdev->callback_thread, (void **)NULL);
439 } else {
440 pthread_mutex_unlock(&stdev->lock);
441 }
442
Eric Laurentcbca9052014-04-18 17:54:10 -0700443 return status;
444}
445
446static int stdev_start_recognition(const struct sound_trigger_hw_device *dev,
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800447 sound_model_handle_t handle,
Eric Laurent30f3e6d2014-07-06 16:08:45 -0700448 const struct sound_trigger_recognition_config *config,
Eric Laurentcbca9052014-04-18 17:54:10 -0700449 recognition_callback_t callback,
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800450 void *cookie) {
451 ALOGI("%s", __func__);
Eric Laurentcbca9052014-04-18 17:54:10 -0700452 struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
Eric Laurentcbca9052014-04-18 17:54:10 -0700453 pthread_mutex_lock(&stdev->lock);
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800454
455 struct recognition_context *model_context = NULL;
456 if (stdev->root_model_context) {
457 struct recognition_context *last_model_context = stdev->root_model_context;
458 while(last_model_context) {
459 if (last_model_context->model_handle == handle) {
460 model_context = last_model_context;
461 break;
462 }
463 last_model_context = last_model_context->next;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800464 }
Eric Laurentcbca9052014-04-18 17:54:10 -0700465 }
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800466 if (!model_context) {
467 ALOGW("Can't find sound model handle %d in registered list", handle);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800468 pthread_mutex_unlock(&stdev->lock);
469 return -ENOSYS;
Eric Laurentcbca9052014-04-18 17:54:10 -0700470 }
471
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800472 free(model_context->config);
473 model_context->config = NULL;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800474 if (config) {
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800475 model_context->config = malloc(sizeof(*config));
476 if (!model_context->config) {
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800477 pthread_mutex_unlock(&stdev->lock);
478 return -ENOMEM;
479 }
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800480 memcpy(model_context->config, config, sizeof(*config));
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800481 }
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800482 model_context->recognition_callback = callback;
483 model_context->recognition_cookie = cookie;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800484
Eric Laurentcbca9052014-04-18 17:54:10 -0700485 pthread_create(&stdev->callback_thread, (const pthread_attr_t *) NULL,
486 callback_thread_loop, stdev);
Eric Laurentcbca9052014-04-18 17:54:10 -0700487 pthread_mutex_unlock(&stdev->lock);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800488 return 0;
Eric Laurentcbca9052014-04-18 17:54:10 -0700489}
490
491static int stdev_stop_recognition(const struct sound_trigger_hw_device *dev,
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800492 sound_model_handle_t handle) {
Eric Laurentcbca9052014-04-18 17:54:10 -0700493 struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800494 ALOGI("%s", __func__);
Eric Laurentcbca9052014-04-18 17:54:10 -0700495 pthread_mutex_lock(&stdev->lock);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800496
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800497 struct recognition_context *model_context = NULL;
498 bool other_callbacks_found = false;
499 if (stdev->root_model_context) {
500 struct recognition_context *last_model_context = stdev->root_model_context;
501 while(last_model_context) {
502 if (last_model_context->model_handle == handle) {
503 model_context = last_model_context;
504 } else if (last_model_context->recognition_callback != NULL) {
505 other_callbacks_found = true;
506 }
507 last_model_context = last_model_context->next;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800508 }
Eric Laurentcbca9052014-04-18 17:54:10 -0700509 }
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800510 if (!model_context) {
511 ALOGW("Can't find sound model handle %d in registered list", handle);
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800512 pthread_mutex_unlock(&stdev->lock);
513 return -ENOSYS;
Eric Laurentcbca9052014-04-18 17:54:10 -0700514 }
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800515
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800516 free(model_context->config);
517 model_context->config = NULL;
518 model_context->recognition_callback = NULL;
519 model_context->recognition_cookie = NULL;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800520
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800521 /* If no more models running with callbacks, stop trigger thread */
522 if (!other_callbacks_found) {
523 send_loop_kill_signal();
524 pthread_mutex_unlock(&stdev->lock);
525 pthread_join(stdev->callback_thread, (void **)NULL);
526 } else {
527 pthread_mutex_unlock(&stdev->lock);
528 }
529
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800530 return 0;
Eric Laurentcbca9052014-04-18 17:54:10 -0700531}
532
Ryan Bavettabe0c8fd2016-02-01 15:17:12 -0800533__attribute__ ((visibility ("default")))
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800534int sound_trigger_open_for_streaming() {
Ryan Bavettabe0c8fd2016-02-01 15:17:12 -0800535 int ret = 0;
536 return ret;
537}
538
539__attribute__ ((visibility ("default")))
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800540size_t sound_trigger_read_samples(int audio_handle, void *buffer, size_t buffer_len) {
Ryan Bavettabe0c8fd2016-02-01 15:17:12 -0800541 size_t ret = 0;
542 return ret;
543}
544
545__attribute__ ((visibility ("default")))
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800546int sound_trigger_close_for_streaming(int audio_handle __unused) {
Ryan Bavettabe0c8fd2016-02-01 15:17:12 -0800547 return 0;
548}
549
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800550static int stdev_close(hw_device_t *device) {
Eric Laurentcbca9052014-04-18 17:54:10 -0700551 free(device);
552 return 0;
553}
554
555static int stdev_open(const hw_module_t* module, const char* name,
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800556 hw_device_t** device) {
Eric Laurentcbca9052014-04-18 17:54:10 -0700557 struct stub_sound_trigger_device *stdev;
558 int ret;
559
560 if (strcmp(name, SOUND_TRIGGER_HARDWARE_INTERFACE) != 0)
561 return -EINVAL;
562
563 stdev = calloc(1, sizeof(struct stub_sound_trigger_device));
564 if (!stdev)
565 return -ENOMEM;
566
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800567 stdev->next_sound_model_id = 1;
Ryan Bavetta4615aad2016-01-27 16:12:04 -0800568
Eric Laurentcbca9052014-04-18 17:54:10 -0700569 stdev->device.common.tag = HARDWARE_DEVICE_TAG;
570 stdev->device.common.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_0;
571 stdev->device.common.module = (struct hw_module_t *) module;
572 stdev->device.common.close = stdev_close;
573 stdev->device.get_properties = stdev_get_properties;
574 stdev->device.load_sound_model = stdev_load_sound_model;
575 stdev->device.unload_sound_model = stdev_unload_sound_model;
576 stdev->device.start_recognition = stdev_start_recognition;
577 stdev->device.stop_recognition = stdev_stop_recognition;
578
579 pthread_mutex_init(&stdev->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurentcbca9052014-04-18 17:54:10 -0700580
581 *device = &stdev->device.common;
582
583 return 0;
584}
585
586static struct hw_module_methods_t hal_module_methods = {
587 .open = stdev_open,
588};
589
590struct sound_trigger_module HAL_MODULE_INFO_SYM = {
591 .common = {
592 .tag = HARDWARE_MODULE_TAG,
593 .module_api_version = SOUND_TRIGGER_MODULE_API_VERSION_1_0,
594 .hal_api_version = HARDWARE_HAL_API_VERSION,
595 .id = SOUND_TRIGGER_HARDWARE_MODULE_ID,
596 .name = "Default sound trigger HAL",
597 .author = "The Android Open Source Project",
598 .methods = &hal_module_methods,
599 },
600};
Ryan Bavettacc6541c2016-02-09 21:20:51 -0800601