1 /*
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
25 #include <system/sound_trigger.h>
26 #include <cutils/atomic.h>
27 #include <cutils/properties.h>
28 #include <hardware/hardware.h>
29 #include <media/AudioSystem.h>
30 #include <utils/Errors.h>
31 #include <utils/Log.h>
32 #include <binder/IServiceManager.h>
33 #include <binder/MemoryBase.h>
34 #include <binder/MemoryHeapBase.h>
35 #include <system/sound_trigger.h>
36 #include <ServiceUtilities.h>
37 #include "SoundTriggerHwService.h"
38
39 #ifdef SOUND_TRIGGER_USE_STUB_MODULE
40 #define HW_MODULE_PREFIX "stub"
41 #else
42 #define HW_MODULE_PREFIX "primary"
43 #endif
44 namespace android {
45
SoundTriggerHwService()46 SoundTriggerHwService::SoundTriggerHwService()
47 : BnSoundTriggerHwService(),
48 mNextUniqueId(1),
49 mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
50 mCaptureState(false)
51 {
52 }
53
onFirstRef()54 void SoundTriggerHwService::onFirstRef()
55 {
56 int rc;
57
58 sp<SoundTriggerHalInterface> halInterface =
59 SoundTriggerHalInterface::connectModule(HW_MODULE_PREFIX);
60
61 if (halInterface == 0) {
62 ALOGW("could not connect to HAL");
63 return;
64 }
65 sound_trigger_module_descriptor descriptor;
66 rc = halInterface->getProperties(&descriptor.properties);
67 if (rc != 0) {
68 ALOGE("could not read implementation properties");
69 return;
70 }
71 descriptor.handle =
72 (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
73 ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
74 descriptor.handle);
75
76 sp<Module> module = new Module(this, halInterface, descriptor);
77 mModules.add(descriptor.handle, module);
78 mCallbackThread = new CallbackThread(this);
79 }
80
~SoundTriggerHwService()81 SoundTriggerHwService::~SoundTriggerHwService()
82 {
83 if (mCallbackThread != 0) {
84 mCallbackThread->exit();
85 }
86 }
87
listModules(struct sound_trigger_module_descriptor * modules,uint32_t * numModules)88 status_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
89 uint32_t *numModules)
90 {
91 ALOGV("listModules");
92 if (!captureHotwordAllowed()) {
93 return PERMISSION_DENIED;
94 }
95
96 AutoMutex lock(mServiceLock);
97 if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
98 return BAD_VALUE;
99 }
100 size_t maxModules = *numModules;
101 *numModules = mModules.size();
102 for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
103 modules[i] = mModules.valueAt(i)->descriptor();
104 }
105 return NO_ERROR;
106 }
107
attach(const sound_trigger_module_handle_t handle,const sp<ISoundTriggerClient> & client,sp<ISoundTrigger> & moduleInterface)108 status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
109 const sp<ISoundTriggerClient>& client,
110 sp<ISoundTrigger>& moduleInterface)
111 {
112 ALOGV("attach module %d", handle);
113 if (!captureHotwordAllowed()) {
114 return PERMISSION_DENIED;
115 }
116
117 AutoMutex lock(mServiceLock);
118 moduleInterface.clear();
119 if (client == 0) {
120 return BAD_VALUE;
121 }
122 ssize_t index = mModules.indexOfKey(handle);
123 if (index < 0) {
124 return BAD_VALUE;
125 }
126 sp<Module> module = mModules.valueAt(index);
127
128 sp<ModuleClient> moduleClient = module->addClient(client);
129 if (moduleClient == 0) {
130 return NO_INIT;
131 }
132
133 moduleClient->setCaptureState_l(mCaptureState);
134 moduleInterface = moduleClient;
135
136 return NO_ERROR;
137 }
138
setCaptureState(bool active)139 status_t SoundTriggerHwService::setCaptureState(bool active)
140 {
141 ALOGV("setCaptureState %d", active);
142 AutoMutex lock(mServiceLock);
143 mCaptureState = active;
144 for (size_t i = 0; i < mModules.size(); i++) {
145 mModules.valueAt(i)->setCaptureState_l(active);
146 }
147 return NO_ERROR;
148 }
149
150
151 static const int kDumpLockRetries = 50;
152 static const int kDumpLockSleep = 60000;
153
tryLock(Mutex & mutex)154 static bool tryLock(Mutex& mutex)
155 {
156 bool locked = false;
157 for (int i = 0; i < kDumpLockRetries; ++i) {
158 if (mutex.tryLock() == NO_ERROR) {
159 locked = true;
160 break;
161 }
162 usleep(kDumpLockSleep);
163 }
164 return locked;
165 }
166
dump(int fd,const Vector<String16> & args __unused)167 status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
168 String8 result;
169 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
170 result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
171 write(fd, result.string(), result.size());
172 } else {
173 bool locked = tryLock(mServiceLock);
174 // failed to lock - SoundTriggerHwService is probably deadlocked
175 if (!locked) {
176 result.append("SoundTriggerHwService may be deadlocked\n");
177 write(fd, result.string(), result.size());
178 }
179
180 if (locked) mServiceLock.unlock();
181 }
182 return NO_ERROR;
183 }
184
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)185 status_t SoundTriggerHwService::onTransact(
186 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
187 return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
188 }
189
190
191 // static
recognitionCallback(struct sound_trigger_recognition_event * event,void * cookie)192 void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
193 void *cookie)
194 {
195 Module *module = (Module *)cookie;
196 if (module == NULL) {
197 return;
198 }
199 sp<SoundTriggerHwService> service = module->service().promote();
200 if (service == 0) {
201 return;
202 }
203
204 service->sendRecognitionEvent(event, module);
205 }
206
prepareRecognitionEvent_l(struct sound_trigger_recognition_event * event)207 sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
208 struct sound_trigger_recognition_event *event)
209 {
210 sp<IMemory> eventMemory;
211
212 //sanitize event
213 switch (event->type) {
214 case SOUND_MODEL_TYPE_KEYPHRASE:
215 ALOGW_IF(event->data_size != 0 && event->data_offset !=
216 sizeof(struct sound_trigger_phrase_recognition_event),
217 "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
218 event->data_offset);
219 event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
220 break;
221 case SOUND_MODEL_TYPE_GENERIC:
222 ALOGW_IF(event->data_size != 0 && event->data_offset !=
223 sizeof(struct sound_trigger_generic_recognition_event),
224 "prepareRecognitionEvent_l(): invalid data offset %u for generic event type",
225 event->data_offset);
226 event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
227 break;
228 case SOUND_MODEL_TYPE_UNKNOWN:
229 ALOGW_IF(event->data_size != 0 && event->data_offset !=
230 sizeof(struct sound_trigger_recognition_event),
231 "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
232 event->data_offset);
233 event->data_offset = sizeof(struct sound_trigger_recognition_event);
234 break;
235 default:
236 return eventMemory;
237 }
238
239 size_t size = event->data_offset + event->data_size;
240 eventMemory = mMemoryDealer->allocate(size);
241 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
242 eventMemory.clear();
243 return eventMemory;
244 }
245 memcpy(eventMemory->pointer(), event, size);
246
247 return eventMemory;
248 }
249
sendRecognitionEvent(struct sound_trigger_recognition_event * event,Module * module)250 void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
251 Module *module)
252 {
253 AutoMutex lock(mServiceLock);
254 if (module == NULL) {
255 return;
256 }
257 sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
258 if (eventMemory == 0) {
259 return;
260 }
261 sp<Module> strongModule;
262 for (size_t i = 0; i < mModules.size(); i++) {
263 if (mModules.valueAt(i).get() == module) {
264 strongModule = mModules.valueAt(i);
265 break;
266 }
267 }
268 if (strongModule == 0) {
269 return;
270 }
271
272 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
273 eventMemory);
274 callbackEvent->setModule(strongModule);
275 sendCallbackEvent_l(callbackEvent);
276 }
277
278 // static
soundModelCallback(struct sound_trigger_model_event * event,void * cookie)279 void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
280 void *cookie)
281 {
282 Module *module = (Module *)cookie;
283 if (module == NULL) {
284 return;
285 }
286 sp<SoundTriggerHwService> service = module->service().promote();
287 if (service == 0) {
288 return;
289 }
290
291 service->sendSoundModelEvent(event, module);
292 }
293
prepareSoundModelEvent_l(struct sound_trigger_model_event * event)294 sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
295 {
296 sp<IMemory> eventMemory;
297
298 size_t size = event->data_offset + event->data_size;
299 eventMemory = mMemoryDealer->allocate(size);
300 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
301 eventMemory.clear();
302 return eventMemory;
303 }
304 memcpy(eventMemory->pointer(), event, size);
305
306 return eventMemory;
307 }
308
sendSoundModelEvent(struct sound_trigger_model_event * event,Module * module)309 void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
310 Module *module)
311 {
312 AutoMutex lock(mServiceLock);
313 sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
314 if (eventMemory == 0) {
315 return;
316 }
317 sp<Module> strongModule;
318 for (size_t i = 0; i < mModules.size(); i++) {
319 if (mModules.valueAt(i).get() == module) {
320 strongModule = mModules.valueAt(i);
321 break;
322 }
323 }
324 if (strongModule == 0) {
325 return;
326 }
327 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
328 eventMemory);
329 callbackEvent->setModule(strongModule);
330 sendCallbackEvent_l(callbackEvent);
331 }
332
333
prepareServiceStateEvent_l(sound_trigger_service_state_t state)334 sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
335 {
336 sp<IMemory> eventMemory;
337
338 size_t size = sizeof(sound_trigger_service_state_t);
339 eventMemory = mMemoryDealer->allocate(size);
340 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
341 eventMemory.clear();
342 return eventMemory;
343 }
344 *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
345 return eventMemory;
346 }
347
348 // call with mServiceLock held
sendServiceStateEvent_l(sound_trigger_service_state_t state,Module * module)349 void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
350 Module *module)
351 {
352 sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
353 if (eventMemory == 0) {
354 return;
355 }
356 sp<Module> strongModule;
357 for (size_t i = 0; i < mModules.size(); i++) {
358 if (mModules.valueAt(i).get() == module) {
359 strongModule = mModules.valueAt(i);
360 break;
361 }
362 }
363 if (strongModule == 0) {
364 return;
365 }
366 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
367 eventMemory);
368 callbackEvent->setModule(strongModule);
369 sendCallbackEvent_l(callbackEvent);
370 }
371
sendServiceStateEvent_l(sound_trigger_service_state_t state,ModuleClient * moduleClient)372 void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
373 ModuleClient *moduleClient)
374 {
375 sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
376 if (eventMemory == 0) {
377 return;
378 }
379 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
380 eventMemory);
381 callbackEvent->setModuleClient(moduleClient);
382 sendCallbackEvent_l(callbackEvent);
383 }
384
385 // call with mServiceLock held
sendCallbackEvent_l(const sp<CallbackEvent> & event)386 void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
387 {
388 mCallbackThread->sendCallbackEvent(event);
389 }
390
onCallbackEvent(const sp<CallbackEvent> & event)391 void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
392 {
393 ALOGV("onCallbackEvent");
394 sp<Module> module;
395 sp<ModuleClient> moduleClient;
396 {
397 AutoMutex lock(mServiceLock);
398 //CallbackEvent is either for Module or ModuleClient
399 module = event->mModule.promote();
400 if (module == 0) {
401 moduleClient = event->mModuleClient.promote();
402 if (moduleClient == 0) {
403 return;
404 }
405 }
406 }
407 if (module != 0) {
408 ALOGV("onCallbackEvent for module");
409 module->onCallbackEvent(event);
410 } else if (moduleClient != 0) {
411 ALOGV("onCallbackEvent for moduleClient");
412 moduleClient->onCallbackEvent(event);
413 }
414 {
415 AutoMutex lock(mServiceLock);
416 // clear now to execute with mServiceLock locked
417 event->mMemory.clear();
418 }
419 }
420
421 #undef LOG_TAG
422 #define LOG_TAG "SoundTriggerHwService::CallbackThread"
423
CallbackThread(const wp<SoundTriggerHwService> & service)424 SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
425 : mService(service)
426 {
427 }
428
~CallbackThread()429 SoundTriggerHwService::CallbackThread::~CallbackThread()
430 {
431 while (!mEventQueue.isEmpty()) {
432 mEventQueue[0]->mMemory.clear();
433 mEventQueue.removeAt(0);
434 }
435 }
436
onFirstRef()437 void SoundTriggerHwService::CallbackThread::onFirstRef()
438 {
439 run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
440 }
441
threadLoop()442 bool SoundTriggerHwService::CallbackThread::threadLoop()
443 {
444 while (!exitPending()) {
445 sp<CallbackEvent> event;
446 sp<SoundTriggerHwService> service;
447 {
448 Mutex::Autolock _l(mCallbackLock);
449 while (mEventQueue.isEmpty() && !exitPending()) {
450 ALOGV("CallbackThread::threadLoop() sleep");
451 mCallbackCond.wait(mCallbackLock);
452 ALOGV("CallbackThread::threadLoop() wake up");
453 }
454 if (exitPending()) {
455 break;
456 }
457 event = mEventQueue[0];
458 mEventQueue.removeAt(0);
459 service = mService.promote();
460 }
461 if (service != 0) {
462 service->onCallbackEvent(event);
463 }
464 }
465 return false;
466 }
467
exit()468 void SoundTriggerHwService::CallbackThread::exit()
469 {
470 Mutex::Autolock _l(mCallbackLock);
471 requestExit();
472 mCallbackCond.broadcast();
473 }
474
sendCallbackEvent(const sp<SoundTriggerHwService::CallbackEvent> & event)475 void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
476 const sp<SoundTriggerHwService::CallbackEvent>& event)
477 {
478 AutoMutex lock(mCallbackLock);
479 mEventQueue.add(event);
480 mCallbackCond.signal();
481 }
482
CallbackEvent(event_type type,sp<IMemory> memory)483 SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory)
484 : mType(type), mMemory(memory)
485 {
486 }
487
~CallbackEvent()488 SoundTriggerHwService::CallbackEvent::~CallbackEvent()
489 {
490 }
491
492
493 #undef LOG_TAG
494 #define LOG_TAG "SoundTriggerHwService::Module"
495
Module(const sp<SoundTriggerHwService> & service,const sp<SoundTriggerHalInterface> & halInterface,sound_trigger_module_descriptor descriptor)496 SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
497 const sp<SoundTriggerHalInterface>& halInterface,
498 sound_trigger_module_descriptor descriptor)
499 : mService(service), mHalInterface(halInterface), mDescriptor(descriptor),
500 mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
501 {
502 }
503
~Module()504 SoundTriggerHwService::Module::~Module() {
505 mModuleClients.clear();
506 }
507
508 sp<SoundTriggerHwService::ModuleClient>
addClient(const sp<ISoundTriggerClient> & client)509 SoundTriggerHwService::Module::addClient(const sp<ISoundTriggerClient>& client)
510 {
511 AutoMutex lock(mLock);
512 sp<ModuleClient> moduleClient;
513
514 for (size_t i = 0; i < mModuleClients.size(); i++) {
515 if (mModuleClients[i]->client() == client) {
516 // Client already present, reuse client
517 return moduleClient;
518 }
519 }
520 moduleClient = new ModuleClient(this, client);
521
522 ALOGV("addClient() client %p", moduleClient.get());
523 mModuleClients.add(moduleClient);
524
525 return moduleClient;
526 }
527
detach(const sp<ModuleClient> & moduleClient)528 void SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient)
529 {
530 ALOGV("Module::detach()");
531 AutoMutex lock(mLock);
532 ssize_t index = -1;
533
534 for (size_t i = 0; i < mModuleClients.size(); i++) {
535 if (mModuleClients[i] == moduleClient) {
536 index = i;
537 break;
538 }
539 }
540 if (index == -1) {
541 return;
542 }
543
544 ALOGV("remove client %p", moduleClient.get());
545 mModuleClients.removeAt(index);
546
547 // Iterate in reverse order as models are removed from list inside the loop.
548 for (size_t i = mModels.size(); i > 0; i--) {
549 sp<Model> model = mModels.valueAt(i - 1);
550 if (moduleClient == model->mModuleClient) {
551 mModels.removeItemsAt(i - 1);
552 ALOGV("detach() unloading model %d", model->mHandle);
553 if (mHalInterface != 0) {
554 if (model->mState == Model::STATE_ACTIVE) {
555 mHalInterface->stopRecognition(model->mHandle);
556 }
557 mHalInterface->unloadSoundModel(model->mHandle);
558 }
559 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
560 mHalInterface->unloadSoundModel(model->mHandle);
561 }
562 }
563 }
564
loadSoundModel(const sp<IMemory> & modelMemory,sp<ModuleClient> moduleClient,sound_model_handle_t * handle)565 status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
566 sp<ModuleClient> moduleClient,
567 sound_model_handle_t *handle)
568 {
569 ALOGV("loadSoundModel() handle");
570 if (mHalInterface == 0) {
571 return NO_INIT;
572 }
573 if (modelMemory == 0 || modelMemory->pointer() == NULL) {
574 ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
575 return BAD_VALUE;
576 }
577 struct sound_trigger_sound_model *sound_model =
578 (struct sound_trigger_sound_model *)modelMemory->pointer();
579
580 size_t structSize;
581 if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
582 structSize = sizeof(struct sound_trigger_phrase_sound_model);
583 } else {
584 structSize = sizeof(struct sound_trigger_sound_model);
585 }
586
587 if (sound_model->data_offset < structSize ||
588 sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
589 modelMemory->size() < sound_model->data_offset ||
590 sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
591 android_errorWriteLog(0x534e4554, "30148546");
592 ALOGE("loadSoundModel() data_size is too big");
593 return BAD_VALUE;
594 }
595
596 AutoMutex lock(mLock);
597
598 if (mModels.size() >= mDescriptor.properties.max_sound_models) {
599 ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
600 mDescriptor.properties.max_sound_models);
601 return INVALID_OPERATION;
602 }
603
604 status_t status = mHalInterface->loadSoundModel(sound_model,
605 SoundTriggerHwService::soundModelCallback,
606 this, handle);
607
608 if (status != NO_ERROR) {
609 return status;
610 }
611 audio_session_t session;
612 audio_io_handle_t ioHandle;
613 audio_devices_t device;
614
615 status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
616 if (status != NO_ERROR) {
617 return status;
618 }
619
620 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
621 moduleClient);
622 mModels.replaceValueFor(*handle, model);
623
624 return status;
625 }
626
unloadSoundModel(sound_model_handle_t handle)627 status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
628 {
629 ALOGV("unloadSoundModel() model handle %d", handle);
630 AutoMutex lock(mLock);
631 return unloadSoundModel_l(handle);
632 }
633
unloadSoundModel_l(sound_model_handle_t handle)634 status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
635 {
636 if (mHalInterface == 0) {
637 return NO_INIT;
638 }
639 ssize_t index = mModels.indexOfKey(handle);
640 if (index < 0) {
641 return BAD_VALUE;
642 }
643 sp<Model> model = mModels.valueAt(index);
644 mModels.removeItem(handle);
645 if (model->mState == Model::STATE_ACTIVE) {
646 mHalInterface->stopRecognition(model->mHandle);
647 model->mState = Model::STATE_IDLE;
648 }
649 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
650 return mHalInterface->unloadSoundModel(handle);
651 }
652
startRecognition(sound_model_handle_t handle,const sp<IMemory> & dataMemory)653 status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
654 const sp<IMemory>& dataMemory)
655 {
656 ALOGV("startRecognition() model handle %d", handle);
657 if (mHalInterface == 0) {
658 return NO_INIT;
659 }
660 if (dataMemory == 0 || dataMemory->pointer() == NULL) {
661 ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
662 return BAD_VALUE;
663
664 }
665
666 struct sound_trigger_recognition_config *config =
667 (struct sound_trigger_recognition_config *)dataMemory->pointer();
668
669 if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
670 config->data_size > (UINT_MAX - config->data_offset) ||
671 dataMemory->size() < config->data_offset ||
672 config->data_size > (dataMemory->size() - config->data_offset)) {
673 ALOGE("startRecognition() data_size is too big");
674 return BAD_VALUE;
675 }
676
677 AutoMutex lock(mLock);
678 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
679 return INVALID_OPERATION;
680 }
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
690
691 //TODO: get capture handle and device from audio policy service
692 config->capture_handle = model->mCaptureIOHandle;
693 config->capture_device = model->mCaptureDevice;
694 status_t status = mHalInterface->startRecognition(handle, config,
695 SoundTriggerHwService::recognitionCallback,
696 this);
697
698 if (status == NO_ERROR) {
699 model->mState = Model::STATE_ACTIVE;
700 model->mConfig = *config;
701 }
702
703 return status;
704 }
705
stopRecognition(sound_model_handle_t handle)706 status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
707 {
708 ALOGV("stopRecognition() model handle %d", handle);
709 if (mHalInterface == 0) {
710 return NO_INIT;
711 }
712 AutoMutex lock(mLock);
713 sp<Model> model = getModel(handle);
714 if (model == 0) {
715 return BAD_VALUE;
716 }
717
718 if (model->mState != Model::STATE_ACTIVE) {
719 return INVALID_OPERATION;
720 }
721 mHalInterface->stopRecognition(handle);
722 model->mState = Model::STATE_IDLE;
723 return NO_ERROR;
724 }
725
onCallbackEvent(const sp<CallbackEvent> & event)726 void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
727 {
728 ALOGV("onCallbackEvent type %d", event->mType);
729
730 sp<IMemory> eventMemory = event->mMemory;
731
732 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
733 return;
734 }
735 if (mModuleClients.isEmpty()) {
736 ALOGI("%s no clients", __func__);
737 return;
738 }
739
740 switch (event->mType) {
741 case CallbackEvent::TYPE_RECOGNITION: {
742 struct sound_trigger_recognition_event *recognitionEvent =
743 (struct sound_trigger_recognition_event *)eventMemory->pointer();
744 sp<ISoundTriggerClient> client;
745 {
746 AutoMutex lock(mLock);
747 sp<Model> model = getModel(recognitionEvent->model);
748 if (model == 0) {
749 ALOGW("%s model == 0", __func__);
750 return;
751 }
752 if (model->mState != Model::STATE_ACTIVE) {
753 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
754 return;
755 }
756
757 recognitionEvent->capture_session = model->mCaptureSession;
758 model->mState = Model::STATE_IDLE;
759 client = model->mModuleClient->client();
760 }
761 if (client != 0) {
762 client->onRecognitionEvent(eventMemory);
763 }
764 } break;
765 case CallbackEvent::TYPE_SOUNDMODEL: {
766 struct sound_trigger_model_event *soundmodelEvent =
767 (struct sound_trigger_model_event *)eventMemory->pointer();
768 sp<ISoundTriggerClient> client;
769 {
770 AutoMutex lock(mLock);
771 sp<Model> model = getModel(soundmodelEvent->model);
772 if (model == 0) {
773 ALOGW("%s model == 0", __func__);
774 return;
775 }
776 client = model->mModuleClient->client();
777 }
778 if (client != 0) {
779 client->onSoundModelEvent(eventMemory);
780 }
781 } break;
782 case CallbackEvent::TYPE_SERVICE_STATE: {
783 Vector< sp<ISoundTriggerClient> > clients;
784 {
785 AutoMutex lock(mLock);
786 for (size_t i = 0; i < mModuleClients.size(); i++) {
787 if (mModuleClients[i] != 0) {
788 clients.add(mModuleClients[i]->client());
789 }
790 }
791 }
792 for (size_t i = 0; i < clients.size(); i++) {
793 clients[i]->onServiceStateChange(eventMemory);
794 }
795 } break;
796 default:
797 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
798 }
799 }
800
getModel(sound_model_handle_t handle)801 sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
802 sound_model_handle_t handle)
803 {
804 sp<Model> model;
805 ssize_t index = mModels.indexOfKey(handle);
806 if (index >= 0) {
807 model = mModels.valueAt(index);
808 }
809 return model;
810 }
811
812 // Called with mServiceLock held
setCaptureState_l(bool active)813 void SoundTriggerHwService::Module::setCaptureState_l(bool active)
814 {
815 ALOGV("Module::setCaptureState_l %d", active);
816 sp<SoundTriggerHwService> service;
817 sound_trigger_service_state_t state;
818
819 Vector< sp<IMemory> > events;
820 {
821 AutoMutex lock(mLock);
822 state = (active && !mDescriptor.properties.concurrent_capture) ?
823 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
824
825 if (state == mServiceState) {
826 return;
827 }
828
829 mServiceState = state;
830
831 service = mService.promote();
832 if (service == 0) {
833 return;
834 }
835
836 if (state == SOUND_TRIGGER_STATE_ENABLED) {
837 goto exit;
838 }
839
840 const bool supports_stop_all =
841 (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() == ENOSYS);
842
843 for (size_t i = 0; i < mModels.size(); i++) {
844 sp<Model> model = mModels.valueAt(i);
845 if (model->mState == Model::STATE_ACTIVE) {
846 if (mHalInterface != 0 && !supports_stop_all) {
847 mHalInterface->stopRecognition(model->mHandle);
848 }
849 // keep model in ACTIVE state so that event is processed by onCallbackEvent()
850 if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
851 struct sound_trigger_phrase_recognition_event event;
852 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
853 event.num_phrases = model->mConfig.num_phrases;
854 for (size_t i = 0; i < event.num_phrases; i++) {
855 event.phrase_extras[i] = model->mConfig.phrases[i];
856 }
857 event.common.status = RECOGNITION_STATUS_ABORT;
858 event.common.type = model->mType;
859 event.common.model = model->mHandle;
860 event.common.data_size = 0;
861 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
862 if (eventMemory != 0) {
863 events.add(eventMemory);
864 }
865 } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
866 struct sound_trigger_generic_recognition_event event;
867 memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
868 event.common.status = RECOGNITION_STATUS_ABORT;
869 event.common.type = model->mType;
870 event.common.model = model->mHandle;
871 event.common.data_size = 0;
872 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
873 if (eventMemory != 0) {
874 events.add(eventMemory);
875 }
876 } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
877 struct sound_trigger_phrase_recognition_event event;
878 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
879 event.common.status = RECOGNITION_STATUS_ABORT;
880 event.common.type = model->mType;
881 event.common.model = model->mHandle;
882 event.common.data_size = 0;
883 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
884 if (eventMemory != 0) {
885 events.add(eventMemory);
886 }
887 } else {
888 goto exit;
889 }
890 }
891 }
892 }
893
894 for (size_t i = 0; i < events.size(); i++) {
895 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
896 events[i]);
897 callbackEvent->setModule(this);
898 service->sendCallbackEvent_l(callbackEvent);
899 }
900
901 exit:
902 service->sendServiceStateEvent_l(state, this);
903 }
904
905
Model(sound_model_handle_t handle,audio_session_t session,audio_io_handle_t ioHandle,audio_devices_t device,sound_trigger_sound_model_type_t type,sp<ModuleClient> & moduleClient)906 SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
907 audio_io_handle_t ioHandle, audio_devices_t device,
908 sound_trigger_sound_model_type_t type,
909 sp<ModuleClient>& moduleClient) :
910 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
911 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type),
912 mModuleClient(moduleClient)
913 {
914 }
915
916 #undef LOG_TAG
917 #define LOG_TAG "SoundTriggerHwService::ModuleClient"
918
ModuleClient(const sp<Module> & module,const sp<ISoundTriggerClient> & client)919 SoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module,
920 const sp<ISoundTriggerClient>& client)
921 : mModule(module), mClient(client)
922 {
923 }
924
onFirstRef()925 void SoundTriggerHwService::ModuleClient::onFirstRef()
926 {
927 sp<IBinder> binder = IInterface::asBinder(mClient);
928 if (binder != 0) {
929 binder->linkToDeath(this);
930 }
931 }
932
~ModuleClient()933 SoundTriggerHwService::ModuleClient::~ModuleClient()
934 {
935 }
936
dump(int fd __unused,const Vector<String16> & args __unused)937 status_t SoundTriggerHwService::ModuleClient::dump(int fd __unused,
938 const Vector<String16>& args __unused) {
939 String8 result;
940 return NO_ERROR;
941 }
942
detach()943 void SoundTriggerHwService::ModuleClient::detach() {
944 ALOGV("detach()");
945 if (!captureHotwordAllowed()) {
946 return;
947 }
948
949 {
950 AutoMutex lock(mLock);
951 if (mClient != 0) {
952 IInterface::asBinder(mClient)->unlinkToDeath(this);
953 mClient.clear();
954 }
955 }
956
957 sp<Module> module = mModule.promote();
958 if (module == 0) {
959 return;
960 }
961 module->detach(this);
962 }
963
loadSoundModel(const sp<IMemory> & modelMemory,sound_model_handle_t * handle)964 status_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory,
965 sound_model_handle_t *handle)
966 {
967 ALOGV("loadSoundModel() handle");
968 if (!captureHotwordAllowed()) {
969 return PERMISSION_DENIED;
970 }
971
972 sp<Module> module = mModule.promote();
973 if (module == 0) {
974 return NO_INIT;
975 }
976 return module->loadSoundModel(modelMemory, this, handle);
977 }
978
unloadSoundModel(sound_model_handle_t handle)979 status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
980 {
981 ALOGV("unloadSoundModel() model handle %d", handle);
982 if (!captureHotwordAllowed()) {
983 return PERMISSION_DENIED;
984 }
985
986 sp<Module> module = mModule.promote();
987 if (module == 0) {
988 return NO_INIT;
989 }
990 return module->unloadSoundModel(handle);
991 }
992
startRecognition(sound_model_handle_t handle,const sp<IMemory> & dataMemory)993 status_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle,
994 const sp<IMemory>& dataMemory)
995 {
996 ALOGV("startRecognition() model handle %d", handle);
997 if (!captureHotwordAllowed()) {
998 return PERMISSION_DENIED;
999 }
1000
1001 sp<Module> module = mModule.promote();
1002 if (module == 0) {
1003 return NO_INIT;
1004 }
1005 return module->startRecognition(handle, dataMemory);
1006 }
1007
stopRecognition(sound_model_handle_t handle)1008 status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
1009 {
1010 ALOGV("stopRecognition() model handle %d", handle);
1011 if (!captureHotwordAllowed()) {
1012 return PERMISSION_DENIED;
1013 }
1014
1015 sp<Module> module = mModule.promote();
1016 if (module == 0) {
1017 return NO_INIT;
1018 }
1019 return module->stopRecognition(handle);
1020 }
1021
setCaptureState_l(bool active)1022 void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
1023 {
1024 ALOGV("ModuleClient::setCaptureState_l %d", active);
1025 sp<SoundTriggerHwService> service;
1026 sound_trigger_service_state_t state;
1027
1028 sp<Module> module = mModule.promote();
1029 if (module == 0) {
1030 return;
1031 }
1032 {
1033 AutoMutex lock(mLock);
1034 state = (active && !module->isConcurrentCaptureAllowed()) ?
1035 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
1036
1037 service = module->service().promote();
1038 if (service == 0) {
1039 return;
1040 }
1041 }
1042 service->sendServiceStateEvent_l(state, this);
1043 }
1044
onCallbackEvent(const sp<CallbackEvent> & event)1045 void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
1046 {
1047 ALOGV("ModuleClient onCallbackEvent type %d", event->mType);
1048
1049 sp<IMemory> eventMemory = event->mMemory;
1050
1051 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
1052 return;
1053 }
1054
1055 switch (event->mType) {
1056 case CallbackEvent::TYPE_SERVICE_STATE: {
1057 sp<ISoundTriggerClient> client;
1058 {
1059 AutoMutex lock(mLock);
1060 client = mClient;
1061 }
1062 if (client !=0 ) {
1063 client->onServiceStateChange(eventMemory);
1064 }
1065 } break;
1066 default:
1067 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
1068 }
1069 }
1070
binderDied(const wp<IBinder> & who __unused)1071 void SoundTriggerHwService::ModuleClient::binderDied(
1072 const wp<IBinder> &who __unused) {
1073 ALOGW("client binder died for client %p", this);
1074 detach();
1075 }
1076
1077 }; // namespace android
1078