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