blob: 894dba0d72e2e3c9fd44444a2e4d120783c55c2e [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)",
64 SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
65 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)",
70 SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
71 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);
146 client->asBinder()->linkToDeath(module);
147 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;
244 case SOUND_MODEL_TYPE_UNKNOWN:
245 ALOGW_IF(event->data_size != 0 && event->data_offset !=
246 sizeof(struct sound_trigger_recognition_event),
247 "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
248 event->data_offset);
249 event->data_offset = sizeof(struct sound_trigger_recognition_event);
250 break;
251 default:
Eric Laurent886561f2014-08-28 19:45:37 -0700252 return eventMemory;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700253 }
254
255 size_t size = event->data_offset + event->data_size;
256 eventMemory = mMemoryDealer->allocate(size);
257 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
258 eventMemory.clear();
259 return eventMemory;
260 }
261 memcpy(eventMemory->pointer(), event, size);
262
263 return eventMemory;
264}
265
266void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
267 Module *module)
268 {
269 AutoMutex lock(mServiceLock);
270 if (module == NULL) {
271 return;
272 }
273 sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
274 if (eventMemory == 0) {
275 return;
276 }
277 sp<Module> strongModule;
278 for (size_t i = 0; i < mModules.size(); i++) {
279 if (mModules.valueAt(i).get() == module) {
280 strongModule = mModules.valueAt(i);
281 break;
282 }
283 }
284 if (strongModule == 0) {
285 return;
286 }
287
288 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
289 eventMemory, strongModule));
290}
291
292// static
293void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
294 void *cookie)
295{
296 Module *module = (Module *)cookie;
297 if (module == NULL) {
298 return;
299 }
300 sp<SoundTriggerHwService> service = module->service().promote();
301 if (service == 0) {
302 return;
303 }
304
305 service->sendSoundModelEvent(event, module);
306}
307
308sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
309{
310 sp<IMemory> eventMemory;
311
312 size_t size = event->data_offset + event->data_size;
313 eventMemory = mMemoryDealer->allocate(size);
314 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
315 eventMemory.clear();
316 return eventMemory;
317 }
318 memcpy(eventMemory->pointer(), event, size);
319
320 return eventMemory;
321}
322
323void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
324 Module *module)
325{
326 AutoMutex lock(mServiceLock);
327 sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
328 if (eventMemory == 0) {
329 return;
330 }
331 sp<Module> strongModule;
332 for (size_t i = 0; i < mModules.size(); i++) {
333 if (mModules.valueAt(i).get() == module) {
334 strongModule = mModules.valueAt(i);
335 break;
336 }
337 }
338 if (strongModule == 0) {
339 return;
340 }
341 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
342 eventMemory, strongModule));
Eric Laurentb7a11d82014-04-18 17:40:41 -0700343}
344
345
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700346sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700347{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700348 sp<IMemory> eventMemory;
349
350 size_t size = sizeof(sound_trigger_service_state_t);
351 eventMemory = mMemoryDealer->allocate(size);
352 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
353 eventMemory.clear();
354 return eventMemory;
355 }
356 *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
357 return eventMemory;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700358}
359
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700360// call with mServiceLock held
361void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
362 Module *module)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700363{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700364 sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
365 if (eventMemory == 0) {
366 return;
367 }
368 sp<Module> strongModule;
369 for (size_t i = 0; i < mModules.size(); i++) {
370 if (mModules.valueAt(i).get() == module) {
371 strongModule = mModules.valueAt(i);
372 break;
373 }
374 }
375 if (strongModule == 0) {
376 return;
377 }
378 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
379 eventMemory, strongModule));
380}
381
382// call with mServiceLock held
383void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
384{
385 mCallbackThread->sendCallbackEvent(event);
386}
387
388void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
389{
390 ALOGV("onCallbackEvent");
Eric Laurentb7a11d82014-04-18 17:40:41 -0700391 sp<Module> module;
392 {
393 AutoMutex lock(mServiceLock);
394 module = event->mModule.promote();
395 if (module == 0) {
396 return;
397 }
398 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700399 module->onCallbackEvent(event);
400 {
401 AutoMutex lock(mServiceLock);
402 // clear now to execute with mServiceLock locked
403 event->mMemory.clear();
404 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700405}
406
407#undef LOG_TAG
408#define LOG_TAG "SoundTriggerHwService::CallbackThread"
409
410SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
411 : mService(service)
412{
413}
414
415SoundTriggerHwService::CallbackThread::~CallbackThread()
416{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700417 while (!mEventQueue.isEmpty()) {
418 mEventQueue[0]->mMemory.clear();
419 mEventQueue.removeAt(0);
420 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700421}
422
423void SoundTriggerHwService::CallbackThread::onFirstRef()
424{
425 run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
426}
427
428bool SoundTriggerHwService::CallbackThread::threadLoop()
429{
430 while (!exitPending()) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700431 sp<CallbackEvent> event;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700432 sp<SoundTriggerHwService> service;
433 {
434 Mutex::Autolock _l(mCallbackLock);
435 while (mEventQueue.isEmpty() && !exitPending()) {
436 ALOGV("CallbackThread::threadLoop() sleep");
437 mCallbackCond.wait(mCallbackLock);
438 ALOGV("CallbackThread::threadLoop() wake up");
439 }
440 if (exitPending()) {
441 break;
442 }
443 event = mEventQueue[0];
444 mEventQueue.removeAt(0);
445 service = mService.promote();
446 }
447 if (service != 0) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700448 service->onCallbackEvent(event);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700449 }
450 }
451 return false;
452}
453
454void SoundTriggerHwService::CallbackThread::exit()
455{
456 Mutex::Autolock _l(mCallbackLock);
457 requestExit();
458 mCallbackCond.broadcast();
459}
460
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700461void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
462 const sp<SoundTriggerHwService::CallbackEvent>& event)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700463{
464 AutoMutex lock(mCallbackLock);
465 mEventQueue.add(event);
466 mCallbackCond.signal();
467}
468
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700469SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory,
470 wp<Module> module)
471 : mType(type), mMemory(memory), mModule(module)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700472{
473}
474
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700475SoundTriggerHwService::CallbackEvent::~CallbackEvent()
Eric Laurentb7a11d82014-04-18 17:40:41 -0700476{
477}
478
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700479
Eric Laurentb7a11d82014-04-18 17:40:41 -0700480#undef LOG_TAG
481#define LOG_TAG "SoundTriggerHwService::Module"
482
483SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
484 sound_trigger_hw_device* hwDevice,
485 sound_trigger_module_descriptor descriptor,
486 const sp<ISoundTriggerClient>& client)
487 : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor),
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700488 mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700489{
490}
491
492SoundTriggerHwService::Module::~Module() {
493}
494
495void SoundTriggerHwService::Module::detach() {
496 ALOGV("detach()");
Eric Laurent8ba53d82014-08-01 23:15:05 +0000497 if (!captureHotwordAllowed()) {
498 return;
499 }
Eric Laurente00e82e2017-10-05 10:58:38 -0700500 Vector<audio_session_t> releasedSessions;
501
Eric Laurentb7a11d82014-04-18 17:40:41 -0700502 {
503 AutoMutex lock(mLock);
504 for (size_t i = 0; i < mModels.size(); i++) {
505 sp<Model> model = mModels.valueAt(i);
506 ALOGV("detach() unloading model %d", model->mHandle);
507 if (model->mState == Model::STATE_ACTIVE) {
508 mHwDevice->stop_recognition(mHwDevice, model->mHandle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700509 }
510 mHwDevice->unload_sound_model(mHwDevice, model->mHandle);
Eric Laurente00e82e2017-10-05 10:58:38 -0700511 releasedSessions.add(model->mCaptureSession);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700512 }
513 mModels.clear();
514 }
Eric Laurente00e82e2017-10-05 10:58:38 -0700515
516 for (size_t i = 0; i < releasedSessions.size(); i++) {
517 // do not call AudioSystem methods with mLock held
518 AudioSystem::releaseSoundTriggerSession(releasedSessions[i]);
519 }
520
Eric Laurentb7a11d82014-04-18 17:40:41 -0700521 if (mClient != 0) {
522 mClient->asBinder()->unlinkToDeath(this);
523 }
524 sp<SoundTriggerHwService> service = mService.promote();
525 if (service == 0) {
526 return;
527 }
528 service->detachModule(this);
529}
530
531status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
532 sound_model_handle_t *handle)
533{
534 ALOGV("loadSoundModel() handle");
Eric Laurent8ba53d82014-08-01 23:15:05 +0000535 if (!captureHotwordAllowed()) {
536 return PERMISSION_DENIED;
537 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700538
539 if (modelMemory == 0 || modelMemory->pointer() == NULL) {
540 ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
541 return BAD_VALUE;
542 }
543 struct sound_trigger_sound_model *sound_model =
544 (struct sound_trigger_sound_model *)modelMemory->pointer();
545
Eric Laurentef0c9152016-08-17 06:19:32 -0700546 size_t structSize;
547 if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
548 structSize = sizeof(struct sound_trigger_phrase_sound_model);
549 } else {
550 structSize = sizeof(struct sound_trigger_sound_model);
551 }
552
553 if (sound_model->data_offset < structSize ||
554 sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
555 modelMemory->size() < sound_model->data_offset ||
556 sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
557 android_errorWriteLog(0x534e4554, "30148546");
558 ALOGE("loadSoundModel() data_size is too big");
559 return BAD_VALUE;
560 }
561
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700562 audio_session_t session;
Eric Laurente00e82e2017-10-05 10:58:38 -0700563 audio_session_t freedSession = AUDIO_SESSION_ALLOCATE;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700564 audio_io_handle_t ioHandle;
565 audio_devices_t device;
Eric Laurente00e82e2017-10-05 10:58:38 -0700566 // do not call AudioSystem methods with mLock held
567 status_t status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700568 if (status != NO_ERROR) {
569 return status;
570 }
571
Eric Laurente00e82e2017-10-05 10:58:38 -0700572 {
573 AutoMutex lock(mLock);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700574
Eric Laurente00e82e2017-10-05 10:58:38 -0700575
576 if (mModels.size() >= mDescriptor.properties.max_sound_models) {
577 if (mModels.size() == 0) {
578 status = INVALID_OPERATION;
579 goto exit;
580 }
581 ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one",
582 mDescriptor.properties.max_sound_models);
583 unloadSoundModel_l(mModels.valueAt(0)->mHandle, &freedSession);
584 }
585
Eric Laurent960b1b22017-11-13 13:02:43 -0800586 status = mHwDevice->load_sound_model(mHwDevice,
587 sound_model,
588 SoundTriggerHwService::soundModelCallback,
589 this,
590 handle);
Eric Laurente00e82e2017-10-05 10:58:38 -0700591 if (status != NO_ERROR) {
592 goto exit;
593 }
594
595 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type);
596 mModels.replaceValueFor(*handle, model);
597 }
598
599exit:
600 if (freedSession != AUDIO_SESSION_ALLOCATE) {
601 // do not call AudioSystem methods with mLock held
602 AudioSystem::releaseSoundTriggerSession(freedSession);
603 }
604 if (status != NO_ERROR) {
605 // do not call AudioSystem methods with mLock held
606 AudioSystem::releaseSoundTriggerSession(session);
607 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700608 return status;
609}
610
611status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
612{
613 ALOGV("unloadSoundModel() model handle %d", handle);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000614 if (!captureHotwordAllowed()) {
615 return PERMISSION_DENIED;
616 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700617
Eric Laurente00e82e2017-10-05 10:58:38 -0700618 status_t status;
619 audio_session_t freedSession = AUDIO_SESSION_ALLOCATE;
620 {
621 AutoMutex lock(mLock);
622 status = unloadSoundModel_l(handle, &freedSession);
623 }
624 if (freedSession != AUDIO_SESSION_ALLOCATE) {
625 AudioSystem::releaseSoundTriggerSession(freedSession);
626 }
627 return status;
Eric Laurent02eb47c2014-11-20 10:10:20 -0800628}
629
Eric Laurente00e82e2017-10-05 10:58:38 -0700630status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle, audio_session_t *session)
Eric Laurent02eb47c2014-11-20 10:10:20 -0800631{
Eric Laurente00e82e2017-10-05 10:58:38 -0700632 *session = AUDIO_SESSION_ALLOCATE;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700633 ssize_t index = mModels.indexOfKey(handle);
634 if (index < 0) {
635 return BAD_VALUE;
636 }
Eric Laurent1a1cba82014-06-09 16:20:05 -0700637 sp<Model> model = mModels.valueAt(index);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700638 mModels.removeItem(handle);
Eric Laurent1a1cba82014-06-09 16:20:05 -0700639 if (model->mState == Model::STATE_ACTIVE) {
640 mHwDevice->stop_recognition(mHwDevice, model->mHandle);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800641 model->mState = Model::STATE_IDLE;
Eric Laurent1a1cba82014-06-09 16:20:05 -0700642 }
Eric Laurente00e82e2017-10-05 10:58:38 -0700643 *session = model->mCaptureSession;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700644 return mHwDevice->unload_sound_model(mHwDevice, handle);
645}
646
647status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
Eric Laurent0832b2d2014-07-06 16:17:25 -0700648 const sp<IMemory>& dataMemory)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700649{
650 ALOGV("startRecognition() model handle %d", handle);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000651 if (!captureHotwordAllowed()) {
652 return PERMISSION_DENIED;
653 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700654
Eric Laurentef0c9152016-08-17 06:19:32 -0700655 if (dataMemory == 0 || dataMemory->pointer() == NULL) {
656 ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
Eric Laurentb7a11d82014-04-18 17:40:41 -0700657 return BAD_VALUE;
658
659 }
Eric Laurentef0c9152016-08-17 06:19:32 -0700660
661 struct sound_trigger_recognition_config *config =
662 (struct sound_trigger_recognition_config *)dataMemory->pointer();
663
664 if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
665 config->data_size > (UINT_MAX - config->data_offset) ||
666 dataMemory->size() < config->data_offset ||
667 config->data_size > (dataMemory->size() - config->data_offset)) {
668 ALOGE("startRecognition() data_size is too big");
669 return BAD_VALUE;
670 }
671
Eric Laurentb7a11d82014-04-18 17:40:41 -0700672 AutoMutex lock(mLock);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700673 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
674 return INVALID_OPERATION;
675 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700676 sp<Model> model = getModel(handle);
677 if (model == 0) {
678 return BAD_VALUE;
679 }
680
681 if (model->mState == Model::STATE_ACTIVE) {
682 return INVALID_OPERATION;
683 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700684
Eric Laurentb7a11d82014-04-18 17:40:41 -0700685
686 //TODO: get capture handle and device from audio policy service
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700687 config->capture_handle = model->mCaptureIOHandle;
688 config->capture_device = model->mCaptureDevice;
689 status_t status = mHwDevice->start_recognition(mHwDevice, handle, config,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700690 SoundTriggerHwService::recognitionCallback,
Eric Laurent0832b2d2014-07-06 16:17:25 -0700691 this);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700692
693 if (status == NO_ERROR) {
694 model->mState = Model::STATE_ACTIVE;
695 model->mConfig = *config;
696 }
697
698 return status;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700699}
700
701status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
702{
703 ALOGV("stopRecognition() model handle %d", handle);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000704 if (!captureHotwordAllowed()) {
705 return PERMISSION_DENIED;
706 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700707
708 AutoMutex lock(mLock);
709 sp<Model> model = getModel(handle);
710 if (model == 0) {
711 return BAD_VALUE;
712 }
713
714 if (model->mState != Model::STATE_ACTIVE) {
715 return INVALID_OPERATION;
716 }
717 mHwDevice->stop_recognition(mHwDevice, handle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700718 model->mState = Model::STATE_IDLE;
719 return NO_ERROR;
720}
721
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700722
723void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700724{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700725 ALOGV("onCallbackEvent type %d", event->mType);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700726
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700727 sp<IMemory> eventMemory = event->mMemory;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700728
729 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
730 return;
731 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700732 if (mClient == 0) {
733 ALOGI("%s mClient == 0", __func__);
734 return;
735 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700736
737 switch (event->mType) {
738 case CallbackEvent::TYPE_RECOGNITION: {
739 struct sound_trigger_recognition_event *recognitionEvent =
740 (struct sound_trigger_recognition_event *)eventMemory->pointer();
Eric Laurent886561f2014-08-28 19:45:37 -0700741 sp<ISoundTriggerClient> client;
742 {
743 AutoMutex lock(mLock);
744 sp<Model> model = getModel(recognitionEvent->model);
745 if (model == 0) {
746 ALOGW("%s model == 0", __func__);
747 return;
748 }
749 if (model->mState != Model::STATE_ACTIVE) {
750 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
751 return;
752 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700753
Eric Laurent886561f2014-08-28 19:45:37 -0700754 recognitionEvent->capture_session = model->mCaptureSession;
755 model->mState = Model::STATE_IDLE;
756 client = mClient;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700757 }
Eric Laurent886561f2014-08-28 19:45:37 -0700758 if (client != 0) {
759 client->onRecognitionEvent(eventMemory);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700760 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700761 } break;
762 case CallbackEvent::TYPE_SOUNDMODEL: {
763 struct sound_trigger_model_event *soundmodelEvent =
764 (struct sound_trigger_model_event *)eventMemory->pointer();
Eric Laurent886561f2014-08-28 19:45:37 -0700765 sp<ISoundTriggerClient> client;
766 {
767 AutoMutex lock(mLock);
768 sp<Model> model = getModel(soundmodelEvent->model);
769 if (model == 0) {
770 ALOGW("%s model == 0", __func__);
771 return;
772 }
773 client = mClient;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700774 }
Eric Laurent886561f2014-08-28 19:45:37 -0700775 if (client != 0) {
776 client->onSoundModelEvent(eventMemory);
777 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700778 } break;
779 case CallbackEvent::TYPE_SERVICE_STATE: {
Eric Laurent886561f2014-08-28 19:45:37 -0700780 sp<ISoundTriggerClient> client;
781 {
782 AutoMutex lock(mLock);
783 client = mClient;
784 }
785 if (client != 0) {
786 client->onServiceStateChange(eventMemory);
787 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700788 } break;
789 default:
790 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
791 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700792}
793
794sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
795 sound_model_handle_t handle)
796{
797 sp<Model> model;
798 ssize_t index = mModels.indexOfKey(handle);
799 if (index >= 0) {
800 model = mModels.valueAt(index);
801 }
802 return model;
803}
804
805void SoundTriggerHwService::Module::binderDied(
806 const wp<IBinder> &who __unused) {
807 ALOGW("client binder died for module %d", mDescriptor.handle);
808 detach();
809}
810
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700811// Called with mServiceLock held
812void SoundTriggerHwService::Module::setCaptureState_l(bool active)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700813{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700814 ALOGV("Module::setCaptureState_l %d", active);
815 sp<SoundTriggerHwService> service;
816 sound_trigger_service_state_t state;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700817
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700818 Vector< sp<IMemory> > events;
819 {
820 AutoMutex lock(mLock);
821 state = (active && !mDescriptor.properties.concurrent_capture) ?
822 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700823
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700824 if (state == mServiceState) {
825 return;
826 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700827
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700828 mServiceState = state;
829
830 service = mService.promote();
831 if (service == 0) {
832 return;
833 }
834
835 if (state == SOUND_TRIGGER_STATE_ENABLED) {
836 goto exit;
837 }
838
839 for (size_t i = 0; i < mModels.size(); i++) {
840 sp<Model> model = mModels.valueAt(i);
841 if (model->mState == Model::STATE_ACTIVE) {
842 mHwDevice->stop_recognition(mHwDevice, model->mHandle);
843 // keep model in ACTIVE state so that event is processed by onCallbackEvent()
844 struct sound_trigger_phrase_recognition_event phraseEvent;
845 switch (model->mType) {
846 case SOUND_MODEL_TYPE_KEYPHRASE:
847 phraseEvent.num_phrases = model->mConfig.num_phrases;
848 for (size_t i = 0; i < phraseEvent.num_phrases; i++) {
849 phraseEvent.phrase_extras[i] = model->mConfig.phrases[i];
850 }
851 break;
852 case SOUND_MODEL_TYPE_UNKNOWN:
853 default:
854 break;
855 }
856 phraseEvent.common.status = RECOGNITION_STATUS_ABORT;
857 phraseEvent.common.type = model->mType;
858 phraseEvent.common.model = model->mHandle;
859 phraseEvent.common.data_size = 0;
860 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&phraseEvent.common);
861 if (eventMemory != 0) {
862 events.add(eventMemory);
863 }
864 }
865 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700866 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700867
868 for (size_t i = 0; i < events.size(); i++) {
869 service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i],
870 this));
871 }
872
873exit:
874 service->sendServiceStateEvent_l(state, this);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700875}
876
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700877
878SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
879 audio_io_handle_t ioHandle, audio_devices_t device,
880 sound_trigger_sound_model_type_t type) :
881 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
882 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700883{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700884
Eric Laurentb7a11d82014-04-18 17:40:41 -0700885}
886
887status_t SoundTriggerHwService::Module::dump(int fd __unused,
888 const Vector<String16>& args __unused) {
889 String8 result;
890 return NO_ERROR;
891}
892
893}; // namespace android