blob: 66310b5e6187ae36b58433ead440c227530e468e [file] [log] [blame]
Eric Laurentb7a11d82014-04-18 17:40:41 -07001/*
2 * Copyright (C) 2014 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
17#define LOG_TAG "SoundTriggerHwService"
18//#define LOG_NDEBUG 0
19
20#include <stdio.h>
21#include <string.h>
22#include <sys/types.h>
23#include <pthread.h>
24
Eric Laurent8ba53d82014-08-01 23:15:05 +000025#include <system/sound_trigger.h>
26#include <cutils/atomic.h>
27#include <cutils/properties.h>
Eric Laurentdf3dc7e2014-07-27 18:39:40 -070028#include <hardware/hardware.h>
29#include <media/AudioSystem.h>
Eric Laurent8ba53d82014-08-01 23:15:05 +000030#include <utils/Errors.h>
31#include <utils/Log.h>
Eric Laurentb7a11d82014-04-18 17:40:41 -070032#include <binder/IServiceManager.h>
33#include <binder/MemoryBase.h>
34#include <binder/MemoryHeapBase.h>
Eric Laurent936c84a2014-07-17 10:26:04 -070035#include <hardware/sound_trigger.h>
Eric Laurent8ba53d82014-08-01 23:15:05 +000036#include <ServiceUtilities.h>
37#include "SoundTriggerHwService.h"
Eric Laurentb7a11d82014-04-18 17:40:41 -070038
39namespace android {
40
41#ifdef SOUND_TRIGGER_USE_STUB_MODULE
42#define HW_MODULE_PREFIX "stub"
43#else
44#define HW_MODULE_PREFIX "primary"
45#endif
46
47SoundTriggerHwService::SoundTriggerHwService()
48 : BnSoundTriggerHwService(),
Eric Laurentdf3dc7e2014-07-27 18:39:40 -070049 mNextUniqueId(1),
50 mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
51 mCaptureState(false)
Eric Laurentb7a11d82014-04-18 17:40:41 -070052{
53}
54
55void SoundTriggerHwService::onFirstRef()
56{
57 const hw_module_t *mod;
58 int rc;
59 sound_trigger_hw_device *dev;
60
61 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, &mod);
62 if (rc != 0) {
63 ALOGE("couldn't load sound trigger module %s.%s (%s)",
Ryan Bavetta9609a912016-01-28 19:22:29 -080064 SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, strerror(-rc));
Eric Laurentb7a11d82014-04-18 17:40:41 -070065 return;
66 }
67 rc = sound_trigger_hw_device_open(mod, &dev);
68 if (rc != 0) {
69 ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
Ryan Bavetta9609a912016-01-28 19:22:29 -080070 SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, strerror(-rc));
Eric Laurentb7a11d82014-04-18 17:40:41 -070071 return;
72 }
73 if (dev->common.version != SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
74 ALOGE("wrong sound trigger hw device version %04x", dev->common.version);
75 return;
76 }
77
78 sound_trigger_module_descriptor descriptor;
79 rc = dev->get_properties(dev, &descriptor.properties);
80 if (rc != 0) {
81 ALOGE("could not read implementation properties");
82 return;
83 }
84 descriptor.handle =
85 (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
86 ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
87 descriptor.handle);
88
89 sp<ISoundTriggerClient> client;
90 sp<Module> module = new Module(this, dev, descriptor, client);
91 mModules.add(descriptor.handle, module);
92 mCallbackThread = new CallbackThread(this);
93}
94
95SoundTriggerHwService::~SoundTriggerHwService()
96{
97 if (mCallbackThread != 0) {
98 mCallbackThread->exit();
99 }
100 for (size_t i = 0; i < mModules.size(); i++) {
101 sound_trigger_hw_device_close(mModules.valueAt(i)->hwDevice());
102 }
103}
104
105status_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
106 uint32_t *numModules)
107{
108 ALOGV("listModules");
Eric Laurent8ba53d82014-08-01 23:15:05 +0000109 if (!captureHotwordAllowed()) {
110 return PERMISSION_DENIED;
111 }
112
Eric Laurentb7a11d82014-04-18 17:40:41 -0700113 AutoMutex lock(mServiceLock);
114 if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
115 return BAD_VALUE;
116 }
117 size_t maxModules = *numModules;
118 *numModules = mModules.size();
119 for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
120 modules[i] = mModules.valueAt(i)->descriptor();
121 }
122 return NO_ERROR;
123}
124
125status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
126 const sp<ISoundTriggerClient>& client,
127 sp<ISoundTrigger>& moduleInterface)
128{
129 ALOGV("attach module %d", handle);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000130 if (!captureHotwordAllowed()) {
131 return PERMISSION_DENIED;
132 }
133
Eric Laurentb7a11d82014-04-18 17:40:41 -0700134 AutoMutex lock(mServiceLock);
135 moduleInterface.clear();
136 if (client == 0) {
137 return BAD_VALUE;
138 }
139 ssize_t index = mModules.indexOfKey(handle);
140 if (index < 0) {
141 return BAD_VALUE;
142 }
143 sp<Module> module = mModules.valueAt(index);
144
145 module->setClient(client);
Marco Nelissenf8880202014-11-14 07:58:25 -0800146 IInterface::asBinder(client)->linkToDeath(module);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700147 moduleInterface = module;
148
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700149 module->setCaptureState_l(mCaptureState);
150
Eric Laurentb7a11d82014-04-18 17:40:41 -0700151 return NO_ERROR;
152}
153
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700154status_t SoundTriggerHwService::setCaptureState(bool active)
155{
156 ALOGV("setCaptureState %d", active);
157 AutoMutex lock(mServiceLock);
158 mCaptureState = active;
159 for (size_t i = 0; i < mModules.size(); i++) {
160 mModules.valueAt(i)->setCaptureState_l(active);
161 }
162 return NO_ERROR;
163}
164
165
166void SoundTriggerHwService::detachModule(sp<Module> module)
167{
Eric Laurent936c84a2014-07-17 10:26:04 -0700168 ALOGV("detachModule");
Eric Laurent8ba53d82014-08-01 23:15:05 +0000169 AutoMutex lock(mServiceLock);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700170 module->clearClient();
171}
172
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700173
Eric Laurentb7a11d82014-04-18 17:40:41 -0700174static const int kDumpLockRetries = 50;
175static const int kDumpLockSleep = 60000;
176
177static bool tryLock(Mutex& mutex)
178{
179 bool locked = false;
180 for (int i = 0; i < kDumpLockRetries; ++i) {
181 if (mutex.tryLock() == NO_ERROR) {
182 locked = true;
183 break;
184 }
185 usleep(kDumpLockSleep);
186 }
187 return locked;
188}
189
190status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
191 String8 result;
192 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
193 result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
194 write(fd, result.string(), result.size());
195 } else {
196 bool locked = tryLock(mServiceLock);
197 // failed to lock - SoundTriggerHwService is probably deadlocked
198 if (!locked) {
199 result.append("SoundTriggerHwService may be deadlocked\n");
200 write(fd, result.string(), result.size());
201 }
202
203 if (locked) mServiceLock.unlock();
204 }
205 return NO_ERROR;
206}
207
208status_t SoundTriggerHwService::onTransact(
209 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
210 return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
211}
212
213
214// static
215void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
216 void *cookie)
217{
218 Module *module = (Module *)cookie;
219 if (module == NULL) {
220 return;
221 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700222 sp<SoundTriggerHwService> service = module->service().promote();
223 if (service == 0) {
224 return;
225 }
226
227 service->sendRecognitionEvent(event, module);
228}
229
230sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
231 struct sound_trigger_recognition_event *event)
232{
233 sp<IMemory> eventMemory;
234
235 //sanitize event
236 switch (event->type) {
237 case SOUND_MODEL_TYPE_KEYPHRASE:
238 ALOGW_IF(event->data_size != 0 && event->data_offset !=
239 sizeof(struct sound_trigger_phrase_recognition_event),
240 "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
241 event->data_offset);
242 event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
243 break;
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800244 case SOUND_MODEL_TYPE_GENERIC:
245 ALOGW_IF(event->data_size != 0 && event->data_offset !=
246 sizeof(struct sound_trigger_generic_recognition_event),
247 "prepareRecognitionEvent_l(): invalid data offset %u for generic event type",
248 event->data_offset);
249 event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
250 break;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700251 case SOUND_MODEL_TYPE_UNKNOWN:
252 ALOGW_IF(event->data_size != 0 && event->data_offset !=
253 sizeof(struct sound_trigger_recognition_event),
254 "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
255 event->data_offset);
256 event->data_offset = sizeof(struct sound_trigger_recognition_event);
257 break;
258 default:
Eric Laurent886561f2014-08-28 19:45:37 -0700259 return eventMemory;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700260 }
261
262 size_t size = event->data_offset + event->data_size;
263 eventMemory = mMemoryDealer->allocate(size);
264 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
265 eventMemory.clear();
266 return eventMemory;
267 }
268 memcpy(eventMemory->pointer(), event, size);
269
270 return eventMemory;
271}
272
273void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
274 Module *module)
275 {
276 AutoMutex lock(mServiceLock);
277 if (module == NULL) {
278 return;
279 }
280 sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
281 if (eventMemory == 0) {
282 return;
283 }
284 sp<Module> strongModule;
285 for (size_t i = 0; i < mModules.size(); i++) {
286 if (mModules.valueAt(i).get() == module) {
287 strongModule = mModules.valueAt(i);
288 break;
289 }
290 }
291 if (strongModule == 0) {
292 return;
293 }
294
295 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
296 eventMemory, strongModule));
297}
298
299// static
300void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
301 void *cookie)
302{
303 Module *module = (Module *)cookie;
304 if (module == NULL) {
305 return;
306 }
307 sp<SoundTriggerHwService> service = module->service().promote();
308 if (service == 0) {
309 return;
310 }
311
312 service->sendSoundModelEvent(event, module);
313}
314
315sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
316{
317 sp<IMemory> eventMemory;
318
319 size_t size = event->data_offset + event->data_size;
320 eventMemory = mMemoryDealer->allocate(size);
321 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
322 eventMemory.clear();
323 return eventMemory;
324 }
325 memcpy(eventMemory->pointer(), event, size);
326
327 return eventMemory;
328}
329
330void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
331 Module *module)
332{
333 AutoMutex lock(mServiceLock);
334 sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
335 if (eventMemory == 0) {
336 return;
337 }
338 sp<Module> strongModule;
339 for (size_t i = 0; i < mModules.size(); i++) {
340 if (mModules.valueAt(i).get() == module) {
341 strongModule = mModules.valueAt(i);
342 break;
343 }
344 }
345 if (strongModule == 0) {
346 return;
347 }
348 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
349 eventMemory, strongModule));
Eric Laurentb7a11d82014-04-18 17:40:41 -0700350}
351
352
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700353sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700354{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700355 sp<IMemory> eventMemory;
356
357 size_t size = sizeof(sound_trigger_service_state_t);
358 eventMemory = mMemoryDealer->allocate(size);
359 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
360 eventMemory.clear();
361 return eventMemory;
362 }
363 *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
364 return eventMemory;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700365}
366
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700367// call with mServiceLock held
368void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
369 Module *module)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700370{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700371 sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
372 if (eventMemory == 0) {
373 return;
374 }
375 sp<Module> strongModule;
376 for (size_t i = 0; i < mModules.size(); i++) {
377 if (mModules.valueAt(i).get() == module) {
378 strongModule = mModules.valueAt(i);
379 break;
380 }
381 }
382 if (strongModule == 0) {
383 return;
384 }
385 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
386 eventMemory, strongModule));
387}
388
389// call with mServiceLock held
390void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
391{
392 mCallbackThread->sendCallbackEvent(event);
393}
394
395void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
396{
397 ALOGV("onCallbackEvent");
Eric Laurentb7a11d82014-04-18 17:40:41 -0700398 sp<Module> module;
399 {
400 AutoMutex lock(mServiceLock);
401 module = event->mModule.promote();
402 if (module == 0) {
403 return;
404 }
405 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700406 module->onCallbackEvent(event);
407 {
408 AutoMutex lock(mServiceLock);
409 // clear now to execute with mServiceLock locked
410 event->mMemory.clear();
411 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700412}
413
414#undef LOG_TAG
415#define LOG_TAG "SoundTriggerHwService::CallbackThread"
416
417SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
418 : mService(service)
419{
420}
421
422SoundTriggerHwService::CallbackThread::~CallbackThread()
423{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700424 while (!mEventQueue.isEmpty()) {
425 mEventQueue[0]->mMemory.clear();
426 mEventQueue.removeAt(0);
427 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700428}
429
430void SoundTriggerHwService::CallbackThread::onFirstRef()
431{
432 run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
433}
434
435bool SoundTriggerHwService::CallbackThread::threadLoop()
436{
437 while (!exitPending()) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700438 sp<CallbackEvent> event;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700439 sp<SoundTriggerHwService> service;
440 {
441 Mutex::Autolock _l(mCallbackLock);
442 while (mEventQueue.isEmpty() && !exitPending()) {
443 ALOGV("CallbackThread::threadLoop() sleep");
444 mCallbackCond.wait(mCallbackLock);
445 ALOGV("CallbackThread::threadLoop() wake up");
446 }
447 if (exitPending()) {
448 break;
449 }
450 event = mEventQueue[0];
451 mEventQueue.removeAt(0);
452 service = mService.promote();
453 }
454 if (service != 0) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700455 service->onCallbackEvent(event);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700456 }
457 }
458 return false;
459}
460
461void SoundTriggerHwService::CallbackThread::exit()
462{
463 Mutex::Autolock _l(mCallbackLock);
464 requestExit();
465 mCallbackCond.broadcast();
466}
467
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700468void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
469 const sp<SoundTriggerHwService::CallbackEvent>& event)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700470{
471 AutoMutex lock(mCallbackLock);
472 mEventQueue.add(event);
473 mCallbackCond.signal();
474}
475
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700476SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory,
477 wp<Module> module)
478 : mType(type), mMemory(memory), mModule(module)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700479{
480}
481
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700482SoundTriggerHwService::CallbackEvent::~CallbackEvent()
Eric Laurentb7a11d82014-04-18 17:40:41 -0700483{
484}
485
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700486
Eric Laurentb7a11d82014-04-18 17:40:41 -0700487#undef LOG_TAG
488#define LOG_TAG "SoundTriggerHwService::Module"
489
490SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
491 sound_trigger_hw_device* hwDevice,
492 sound_trigger_module_descriptor descriptor,
493 const sp<ISoundTriggerClient>& client)
494 : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor),
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700495 mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700496{
497}
498
499SoundTriggerHwService::Module::~Module() {
500}
501
502void SoundTriggerHwService::Module::detach() {
503 ALOGV("detach()");
Eric Laurent8ba53d82014-08-01 23:15:05 +0000504 if (!captureHotwordAllowed()) {
505 return;
506 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700507 {
508 AutoMutex lock(mLock);
509 for (size_t i = 0; i < mModels.size(); i++) {
510 sp<Model> model = mModels.valueAt(i);
511 ALOGV("detach() unloading model %d", model->mHandle);
512 if (model->mState == Model::STATE_ACTIVE) {
513 mHwDevice->stop_recognition(mHwDevice, model->mHandle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700514 }
515 mHwDevice->unload_sound_model(mHwDevice, model->mHandle);
516 }
517 mModels.clear();
518 }
519 if (mClient != 0) {
Marco Nelissenf8880202014-11-14 07:58:25 -0800520 IInterface::asBinder(mClient)->unlinkToDeath(this);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700521 }
522 sp<SoundTriggerHwService> service = mService.promote();
523 if (service == 0) {
524 return;
525 }
526 service->detachModule(this);
527}
528
529status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
530 sound_model_handle_t *handle)
531{
532 ALOGV("loadSoundModel() handle");
Eric Laurent8ba53d82014-08-01 23:15:05 +0000533 if (!captureHotwordAllowed()) {
534 return PERMISSION_DENIED;
535 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700536
537 if (modelMemory == 0 || modelMemory->pointer() == NULL) {
538 ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
539 return BAD_VALUE;
540 }
541 struct sound_trigger_sound_model *sound_model =
542 (struct sound_trigger_sound_model *)modelMemory->pointer();
543
544 AutoMutex lock(mLock);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800545
546 if (mModels.size() >= mDescriptor.properties.max_sound_models) {
Ryan Bavetta2c561202016-02-16 14:17:31 -0800547 /* Make space for a keyphrase sound model by first trying to swap out a previously loaded
548 * keyphrase sound model, or if needed, another sound model. This decision would optimally
549 * happen in SoundTriggerHelper, but is happening here because state tracking isn't good
550 * enough in SoundTriggerHelper to ensure that state is consistent between it and the HAL,
551 * nor does sufficient error handling exist to recover from inconsistencies.
552 * Once that exists:
553 * TODO: we should return an error instead of unloading a previous sound model here.
554 */
Eric Laurent02eb47c2014-11-20 10:10:20 -0800555 if (mModels.size() == 0) {
556 return INVALID_OPERATION;
557 }
Ryan Bavetta2c561202016-02-16 14:17:31 -0800558 if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
559 ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one",
560 mDescriptor.properties.max_sound_models);
561 sound_model_handle_t unload_handle = mModels.valueAt(0)->mHandle;
562 for (size_t i = 0; i < mModels.size(); i++) {
563 if (mModels.valueAt(i)->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
564 unload_handle = mModels.keyAt(i);
565 break;
566 }
567 }
568 unloadSoundModel_l(unload_handle);
569 } else {
570 ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
571 mDescriptor.properties.max_sound_models);
572 return INVALID_OPERATION;
573 }
Eric Laurent02eb47c2014-11-20 10:10:20 -0800574 }
575
Ryan Bavetta2c561202016-02-16 14:17:31 -0800576 status_t status = mHwDevice->load_sound_model(mHwDevice, sound_model,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700577 SoundTriggerHwService::soundModelCallback,
Ryan Bavetta2c561202016-02-16 14:17:31 -0800578 this, handle);
579
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700580 if (status != NO_ERROR) {
581 return status;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700582 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700583 audio_session_t session;
584 audio_io_handle_t ioHandle;
585 audio_devices_t device;
586
587 status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
588 if (status != NO_ERROR) {
589 return status;
590 }
591
592 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type);
593 mModels.replaceValueFor(*handle, model);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700594
595 return status;
596}
597
598status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
599{
600 ALOGV("unloadSoundModel() model handle %d", handle);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000601 if (!captureHotwordAllowed()) {
602 return PERMISSION_DENIED;
603 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700604
605 AutoMutex lock(mLock);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800606 return unloadSoundModel_l(handle);
607}
608
609status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
610{
Eric Laurentb7a11d82014-04-18 17:40:41 -0700611 ssize_t index = mModels.indexOfKey(handle);
612 if (index < 0) {
613 return BAD_VALUE;
614 }
Eric Laurent1a1cba82014-06-09 16:20:05 -0700615 sp<Model> model = mModels.valueAt(index);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700616 mModels.removeItem(handle);
Eric Laurent1a1cba82014-06-09 16:20:05 -0700617 if (model->mState == Model::STATE_ACTIVE) {
618 mHwDevice->stop_recognition(mHwDevice, model->mHandle);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800619 model->mState = Model::STATE_IDLE;
Eric Laurent1a1cba82014-06-09 16:20:05 -0700620 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700621 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700622 return mHwDevice->unload_sound_model(mHwDevice, handle);
623}
624
625status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
Eric Laurent0832b2d2014-07-06 16:17:25 -0700626 const sp<IMemory>& dataMemory)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700627{
628 ALOGV("startRecognition() model handle %d", handle);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000629 if (!captureHotwordAllowed()) {
630 return PERMISSION_DENIED;
631 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700632
633 if (dataMemory != 0 && dataMemory->pointer() == NULL) {
634 ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()");
635 return BAD_VALUE;
636
637 }
638 AutoMutex lock(mLock);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700639 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
640 return INVALID_OPERATION;
641 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700642 sp<Model> model = getModel(handle);
643 if (model == 0) {
644 return BAD_VALUE;
645 }
Eric Laurent0832b2d2014-07-06 16:17:25 -0700646 if ((dataMemory == 0) ||
647 (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) {
648 return BAD_VALUE;
649 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700650
651 if (model->mState == Model::STATE_ACTIVE) {
652 return INVALID_OPERATION;
653 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700654
Eric Laurent0832b2d2014-07-06 16:17:25 -0700655 struct sound_trigger_recognition_config *config =
656 (struct sound_trigger_recognition_config *)dataMemory->pointer();
Eric Laurentb7a11d82014-04-18 17:40:41 -0700657
658 //TODO: get capture handle and device from audio policy service
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700659 config->capture_handle = model->mCaptureIOHandle;
660 config->capture_device = model->mCaptureDevice;
661 status_t status = mHwDevice->start_recognition(mHwDevice, handle, config,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700662 SoundTriggerHwService::recognitionCallback,
Eric Laurent0832b2d2014-07-06 16:17:25 -0700663 this);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700664
665 if (status == NO_ERROR) {
666 model->mState = Model::STATE_ACTIVE;
667 model->mConfig = *config;
668 }
669
670 return status;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700671}
672
673status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
674{
675 ALOGV("stopRecognition() model handle %d", handle);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000676 if (!captureHotwordAllowed()) {
677 return PERMISSION_DENIED;
678 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700679
680 AutoMutex lock(mLock);
681 sp<Model> model = getModel(handle);
682 if (model == 0) {
683 return BAD_VALUE;
684 }
685
686 if (model->mState != Model::STATE_ACTIVE) {
687 return INVALID_OPERATION;
688 }
689 mHwDevice->stop_recognition(mHwDevice, handle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700690 model->mState = Model::STATE_IDLE;
691 return NO_ERROR;
692}
693
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700694
695void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700696{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700697 ALOGV("onCallbackEvent type %d", event->mType);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700698
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700699 sp<IMemory> eventMemory = event->mMemory;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700700
701 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
702 return;
703 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700704 if (mClient == 0) {
705 ALOGI("%s mClient == 0", __func__);
706 return;
707 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700708
709 switch (event->mType) {
710 case CallbackEvent::TYPE_RECOGNITION: {
711 struct sound_trigger_recognition_event *recognitionEvent =
712 (struct sound_trigger_recognition_event *)eventMemory->pointer();
Eric Laurent886561f2014-08-28 19:45:37 -0700713 sp<ISoundTriggerClient> client;
714 {
715 AutoMutex lock(mLock);
716 sp<Model> model = getModel(recognitionEvent->model);
717 if (model == 0) {
718 ALOGW("%s model == 0", __func__);
719 return;
720 }
721 if (model->mState != Model::STATE_ACTIVE) {
722 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
723 return;
724 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700725
Eric Laurent886561f2014-08-28 19:45:37 -0700726 recognitionEvent->capture_session = model->mCaptureSession;
727 model->mState = Model::STATE_IDLE;
728 client = mClient;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700729 }
Eric Laurent886561f2014-08-28 19:45:37 -0700730 if (client != 0) {
731 client->onRecognitionEvent(eventMemory);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700732 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700733 } break;
734 case CallbackEvent::TYPE_SOUNDMODEL: {
735 struct sound_trigger_model_event *soundmodelEvent =
736 (struct sound_trigger_model_event *)eventMemory->pointer();
Eric Laurent886561f2014-08-28 19:45:37 -0700737 sp<ISoundTriggerClient> client;
738 {
739 AutoMutex lock(mLock);
740 sp<Model> model = getModel(soundmodelEvent->model);
741 if (model == 0) {
742 ALOGW("%s model == 0", __func__);
743 return;
744 }
745 client = mClient;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700746 }
Eric Laurent886561f2014-08-28 19:45:37 -0700747 if (client != 0) {
748 client->onSoundModelEvent(eventMemory);
749 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700750 } break;
751 case CallbackEvent::TYPE_SERVICE_STATE: {
Eric Laurent886561f2014-08-28 19:45:37 -0700752 sp<ISoundTriggerClient> client;
753 {
754 AutoMutex lock(mLock);
755 client = mClient;
756 }
757 if (client != 0) {
758 client->onServiceStateChange(eventMemory);
759 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700760 } break;
761 default:
762 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
763 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700764}
765
766sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
767 sound_model_handle_t handle)
768{
769 sp<Model> model;
770 ssize_t index = mModels.indexOfKey(handle);
771 if (index >= 0) {
772 model = mModels.valueAt(index);
773 }
774 return model;
775}
776
777void SoundTriggerHwService::Module::binderDied(
778 const wp<IBinder> &who __unused) {
779 ALOGW("client binder died for module %d", mDescriptor.handle);
780 detach();
781}
782
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700783// Called with mServiceLock held
784void SoundTriggerHwService::Module::setCaptureState_l(bool active)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700785{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700786 ALOGV("Module::setCaptureState_l %d", active);
787 sp<SoundTriggerHwService> service;
788 sound_trigger_service_state_t state;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700789
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700790 Vector< sp<IMemory> > events;
791 {
792 AutoMutex lock(mLock);
793 state = (active && !mDescriptor.properties.concurrent_capture) ?
794 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700795
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700796 if (state == mServiceState) {
797 return;
798 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700799
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700800 mServiceState = state;
801
802 service = mService.promote();
803 if (service == 0) {
804 return;
805 }
806
807 if (state == SOUND_TRIGGER_STATE_ENABLED) {
808 goto exit;
809 }
810
811 for (size_t i = 0; i < mModels.size(); i++) {
812 sp<Model> model = mModels.valueAt(i);
813 if (model->mState == Model::STATE_ACTIVE) {
814 mHwDevice->stop_recognition(mHwDevice, model->mHandle);
815 // keep model in ACTIVE state so that event is processed by onCallbackEvent()
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800816 if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
817 struct sound_trigger_phrase_recognition_event event;
818 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
819 event.num_phrases = model->mConfig.num_phrases;
820 for (size_t i = 0; i < event.num_phrases; i++) {
821 event.phrase_extras[i] = model->mConfig.phrases[i];
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700822 }
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800823 event.common.status = RECOGNITION_STATUS_ABORT;
824 event.common.type = model->mType;
825 event.common.model = model->mHandle;
826 event.common.data_size = 0;
827 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
828 if (eventMemory != 0) {
829 events.add(eventMemory);
830 }
831 } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
832 struct sound_trigger_generic_recognition_event event;
833 memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
834 event.common.status = RECOGNITION_STATUS_ABORT;
835 event.common.type = model->mType;
836 event.common.model = model->mHandle;
837 event.common.data_size = 0;
838 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
839 if (eventMemory != 0) {
840 events.add(eventMemory);
841 }
Ryan Bavetta9609a912016-01-28 19:22:29 -0800842 } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
843 struct sound_trigger_phrase_recognition_event event;
844 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
845 event.common.status = RECOGNITION_STATUS_ABORT;
846 event.common.type = model->mType;
847 event.common.model = model->mHandle;
848 event.common.data_size = 0;
849 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
850 if (eventMemory != 0) {
851 events.add(eventMemory);
852 }
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800853 } else {
854 goto exit;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700855 }
856 }
857 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700858 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700859
860 for (size_t i = 0; i < events.size(); i++) {
861 service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i],
862 this));
863 }
864
865exit:
866 service->sendServiceStateEvent_l(state, this);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700867}
868
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700869
870SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
871 audio_io_handle_t ioHandle, audio_devices_t device,
872 sound_trigger_sound_model_type_t type) :
873 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
874 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700875{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700876
Eric Laurentb7a11d82014-04-18 17:40:41 -0700877}
878
879status_t SoundTriggerHwService::Module::dump(int fd __unused,
880 const Vector<String16>& args __unused) {
881 String8 result;
882 return NO_ERROR;
883}
884
885}; // namespace android