blob: 54f9b956baccd50cf350757a151685c3dd1c0d86 [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 Laurent7a544b42016-08-05 19:01:13 -070035#include <system/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
Eric Laurentb7a11d82014-04-18 17:40:41 -070039#ifdef SOUND_TRIGGER_USE_STUB_MODULE
40#define HW_MODULE_PREFIX "stub"
41#else
42#define HW_MODULE_PREFIX "primary"
43#endif
Eric Laurent7a544b42016-08-05 19:01:13 -070044namespace android {
Eric Laurentb7a11d82014-04-18 17:40:41 -070045
46SoundTriggerHwService::SoundTriggerHwService()
47 : BnSoundTriggerHwService(),
Eric Laurentdf3dc7e2014-07-27 18:39:40 -070048 mNextUniqueId(1),
49 mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
50 mCaptureState(false)
Eric Laurentb7a11d82014-04-18 17:40:41 -070051{
52}
53
54void SoundTriggerHwService::onFirstRef()
55{
Eric Laurentb7a11d82014-04-18 17:40:41 -070056 int rc;
Eric Laurentb7a11d82014-04-18 17:40:41 -070057
Eric Laurent7a544b42016-08-05 19:01:13 -070058 sp<SoundTriggerHalInterface> halInterface =
59 SoundTriggerHalInterface::connectModule(HW_MODULE_PREFIX);
Eric Laurentb7a11d82014-04-18 17:40:41 -070060
Eric Laurent7a544b42016-08-05 19:01:13 -070061 if (halInterface == 0) {
62 ALOGW("could not connect to HAL");
63 return;
64 }
Eric Laurentb7a11d82014-04-18 17:40:41 -070065 sound_trigger_module_descriptor descriptor;
Eric Laurent7a544b42016-08-05 19:01:13 -070066 rc = halInterface->getProperties(&descriptor.properties);
Eric Laurentb7a11d82014-04-18 17:40:41 -070067 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
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -070076 sp<Module> module = new Module(this, halInterface, descriptor);
Eric Laurentb7a11d82014-04-18 17:40:41 -070077 mModules.add(descriptor.handle, module);
78 mCallbackThread = new CallbackThread(this);
79}
80
81SoundTriggerHwService::~SoundTriggerHwService()
82{
83 if (mCallbackThread != 0) {
84 mCallbackThread->exit();
85 }
Eric Laurentb7a11d82014-04-18 17:40:41 -070086}
87
88status_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
89 uint32_t *numModules)
90{
91 ALOGV("listModules");
Eric Laurent8ba53d82014-08-01 23:15:05 +000092 if (!captureHotwordAllowed()) {
93 return PERMISSION_DENIED;
94 }
95
Eric Laurentb7a11d82014-04-18 17:40:41 -070096 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
108status_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);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000113 if (!captureHotwordAllowed()) {
114 return PERMISSION_DENIED;
115 }
116
Eric Laurentb7a11d82014-04-18 17:40:41 -0700117 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
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700128 sp<ModuleClient> moduleClient = module->addClient(client);
129 if (moduleClient == 0) {
130 return NO_INIT;
131 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700132
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700133 moduleClient->setCaptureState_l(mCaptureState);
134 moduleInterface = moduleClient;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700135
Eric Laurentb7a11d82014-04-18 17:40:41 -0700136 return NO_ERROR;
137}
138
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700139status_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
Eric Laurentb7a11d82014-04-18 17:40:41 -0700151static const int kDumpLockRetries = 50;
152static const int kDumpLockSleep = 60000;
153
154static 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
167status_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
185status_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
192void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
193 void *cookie)
194{
195 Module *module = (Module *)cookie;
196 if (module == NULL) {
197 return;
198 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700199 sp<SoundTriggerHwService> service = module->service().promote();
200 if (service == 0) {
201 return;
202 }
203
204 service->sendRecognitionEvent(event, module);
205}
206
207sp<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;
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800221 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;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700228 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:
Eric Laurent886561f2014-08-28 19:45:37 -0700236 return eventMemory;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700237 }
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
250void 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
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700272 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
273 eventMemory);
274 callbackEvent->setModule(strongModule);
275 sendCallbackEvent_l(callbackEvent);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700276}
277
278// static
279void 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
294sp<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
309void 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 }
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700327 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
328 eventMemory);
329 callbackEvent->setModule(strongModule);
330 sendCallbackEvent_l(callbackEvent);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700331}
332
333
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700334sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700335{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700336 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;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700346}
347
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700348// call with mServiceLock held
349void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
350 Module *module)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700351{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700352 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 }
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700366 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
367 eventMemory);
368 callbackEvent->setModule(strongModule);
369 sendCallbackEvent_l(callbackEvent);
370}
371
372void 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);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700383}
384
385// call with mServiceLock held
386void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
387{
388 mCallbackThread->sendCallbackEvent(event);
389}
390
391void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
392{
393 ALOGV("onCallbackEvent");
Eric Laurentb7a11d82014-04-18 17:40:41 -0700394 sp<Module> module;
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700395 sp<ModuleClient> moduleClient;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700396 {
397 AutoMutex lock(mServiceLock);
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700398 //CallbackEvent is either for Module or ModuleClient
Eric Laurentb7a11d82014-04-18 17:40:41 -0700399 module = event->mModule.promote();
400 if (module == 0) {
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700401 moduleClient = event->mModuleClient.promote();
402 if (moduleClient == 0) {
403 return;
404 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700405 }
406 }
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700407 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 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700414 {
415 AutoMutex lock(mServiceLock);
416 // clear now to execute with mServiceLock locked
417 event->mMemory.clear();
418 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700419}
420
421#undef LOG_TAG
422#define LOG_TAG "SoundTriggerHwService::CallbackThread"
423
424SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
425 : mService(service)
426{
427}
428
429SoundTriggerHwService::CallbackThread::~CallbackThread()
430{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700431 while (!mEventQueue.isEmpty()) {
432 mEventQueue[0]->mMemory.clear();
433 mEventQueue.removeAt(0);
434 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700435}
436
437void SoundTriggerHwService::CallbackThread::onFirstRef()
438{
439 run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
440}
441
442bool SoundTriggerHwService::CallbackThread::threadLoop()
443{
444 while (!exitPending()) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700445 sp<CallbackEvent> event;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700446 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) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700462 service->onCallbackEvent(event);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700463 }
464 }
465 return false;
466}
467
468void SoundTriggerHwService::CallbackThread::exit()
469{
470 Mutex::Autolock _l(mCallbackLock);
471 requestExit();
472 mCallbackCond.broadcast();
473}
474
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700475void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
476 const sp<SoundTriggerHwService::CallbackEvent>& event)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700477{
478 AutoMutex lock(mCallbackLock);
479 mEventQueue.add(event);
480 mCallbackCond.signal();
481}
482
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700483SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory)
484 : mType(type), mMemory(memory)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700485{
486}
487
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700488SoundTriggerHwService::CallbackEvent::~CallbackEvent()
Eric Laurentb7a11d82014-04-18 17:40:41 -0700489{
490}
491
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700492
Eric Laurentb7a11d82014-04-18 17:40:41 -0700493#undef LOG_TAG
494#define LOG_TAG "SoundTriggerHwService::Module"
495
496SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
Eric Laurent7a544b42016-08-05 19:01:13 -0700497 const sp<SoundTriggerHalInterface>& halInterface,
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700498 sound_trigger_module_descriptor descriptor)
Eric Laurent7a544b42016-08-05 19:01:13 -0700499 : mService(service), mHalInterface(halInterface), mDescriptor(descriptor),
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700500 mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700501{
502}
503
504SoundTriggerHwService::Module::~Module() {
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700505 mModuleClients.clear();
Eric Laurentb7a11d82014-04-18 17:40:41 -0700506}
507
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700508sp<SoundTriggerHwService::ModuleClient>
509SoundTriggerHwService::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
528void 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) {
Eric Laurent8ba53d82014-08-01 23:15:05 +0000541 return;
542 }
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700543
544 ALOGV("remove client %p", moduleClient.get());
545 mModuleClients.removeAt(index);
546
547 for (size_t i = 0; i < mModels.size(); i++) {
548 sp<Model> model = mModels.valueAt(i);
549 if (moduleClient == model->mModuleClient) {
550 mModels.removeItemsAt(i);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700551 ALOGV("detach() unloading model %d", model->mHandle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700552 if (mHalInterface != 0) {
553 if (model->mState == Model::STATE_ACTIVE) {
554 mHalInterface->stopRecognition(model->mHandle);
555 }
556 mHalInterface->unloadSoundModel(model->mHandle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700557 }
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700558 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
559 mHalInterface->unloadSoundModel(model->mHandle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700560 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700561 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700562}
563
564status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700565 sp<ModuleClient> moduleClient,
566 sound_model_handle_t *handle)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700567{
568 ALOGV("loadSoundModel() handle");
Eric Laurent7a544b42016-08-05 19:01:13 -0700569 if (mHalInterface == 0) {
570 return NO_INIT;
571 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700572 if (modelMemory == 0 || modelMemory->pointer() == NULL) {
573 ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
574 return BAD_VALUE;
575 }
576 struct sound_trigger_sound_model *sound_model =
577 (struct sound_trigger_sound_model *)modelMemory->pointer();
578
Eric Laurentbb00d8f2016-08-17 06:19:32 -0700579 size_t structSize;
580 if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
581 structSize = sizeof(struct sound_trigger_phrase_sound_model);
582 } else {
583 structSize = sizeof(struct sound_trigger_sound_model);
584 }
585
586 if (sound_model->data_offset < structSize ||
587 sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
588 modelMemory->size() < sound_model->data_offset ||
589 sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
590 android_errorWriteLog(0x534e4554, "30148546");
591 ALOGE("loadSoundModel() data_size is too big");
592 return BAD_VALUE;
593 }
594
Eric Laurentb7a11d82014-04-18 17:40:41 -0700595 AutoMutex lock(mLock);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800596
597 if (mModels.size() >= mDescriptor.properties.max_sound_models) {
Ryan Bavettaad658992016-04-11 14:25:21 -0700598 ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
599 mDescriptor.properties.max_sound_models);
600 return INVALID_OPERATION;
Eric Laurent02eb47c2014-11-20 10:10:20 -0800601 }
602
Eric Laurent7a544b42016-08-05 19:01:13 -0700603 status_t status = mHalInterface->loadSoundModel(sound_model,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700604 SoundTriggerHwService::soundModelCallback,
Ryan Bavetta2c561202016-02-16 14:17:31 -0800605 this, handle);
606
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700607 if (status != NO_ERROR) {
608 return status;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700609 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700610 audio_session_t session;
611 audio_io_handle_t ioHandle;
612 audio_devices_t device;
613
614 status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
615 if (status != NO_ERROR) {
616 return status;
617 }
618
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700619 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
620 moduleClient);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700621 mModels.replaceValueFor(*handle, model);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700622
623 return status;
624}
625
626status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
627{
628 ALOGV("unloadSoundModel() model handle %d", handle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700629 AutoMutex lock(mLock);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800630 return unloadSoundModel_l(handle);
631}
632
633status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
634{
Eric Laurent7a544b42016-08-05 19:01:13 -0700635 if (mHalInterface == 0) {
636 return NO_INIT;
637 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700638 ssize_t index = mModels.indexOfKey(handle);
639 if (index < 0) {
640 return BAD_VALUE;
641 }
Eric Laurent1a1cba82014-06-09 16:20:05 -0700642 sp<Model> model = mModels.valueAt(index);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700643 mModels.removeItem(handle);
Eric Laurent1a1cba82014-06-09 16:20:05 -0700644 if (model->mState == Model::STATE_ACTIVE) {
Eric Laurent7a544b42016-08-05 19:01:13 -0700645 mHalInterface->stopRecognition(model->mHandle);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800646 model->mState = Model::STATE_IDLE;
Eric Laurent1a1cba82014-06-09 16:20:05 -0700647 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700648 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
Eric Laurent7a544b42016-08-05 19:01:13 -0700649 return mHalInterface->unloadSoundModel(handle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700650}
651
652status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
Eric Laurent0832b2d2014-07-06 16:17:25 -0700653 const sp<IMemory>& dataMemory)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700654{
655 ALOGV("startRecognition() model handle %d", handle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700656 if (mHalInterface == 0) {
657 return NO_INIT;
658 }
Eric Laurentbb00d8f2016-08-17 06:19:32 -0700659 if (dataMemory == 0 || dataMemory->pointer() == NULL) {
660 ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
Eric Laurentb7a11d82014-04-18 17:40:41 -0700661 return BAD_VALUE;
662
663 }
Eric Laurentbb00d8f2016-08-17 06:19:32 -0700664
665 struct sound_trigger_recognition_config *config =
666 (struct sound_trigger_recognition_config *)dataMemory->pointer();
667
668 if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
669 config->data_size > (UINT_MAX - config->data_offset) ||
670 dataMemory->size() < config->data_offset ||
671 config->data_size > (dataMemory->size() - config->data_offset)) {
672 ALOGE("startRecognition() data_size is too big");
673 return BAD_VALUE;
674 }
675
Eric Laurentb7a11d82014-04-18 17:40:41 -0700676 AutoMutex lock(mLock);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700677 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
678 return INVALID_OPERATION;
679 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700680 sp<Model> model = getModel(handle);
681 if (model == 0) {
682 return BAD_VALUE;
683 }
684
685 if (model->mState == Model::STATE_ACTIVE) {
686 return INVALID_OPERATION;
687 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700688
Eric Laurentb7a11d82014-04-18 17:40:41 -0700689
690 //TODO: get capture handle and device from audio policy service
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700691 config->capture_handle = model->mCaptureIOHandle;
692 config->capture_device = model->mCaptureDevice;
Eric Laurent7a544b42016-08-05 19:01:13 -0700693 status_t status = mHalInterface->startRecognition(handle, config,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700694 SoundTriggerHwService::recognitionCallback,
Eric Laurent0832b2d2014-07-06 16:17:25 -0700695 this);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700696
697 if (status == NO_ERROR) {
698 model->mState = Model::STATE_ACTIVE;
699 model->mConfig = *config;
700 }
701
702 return status;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700703}
704
705status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
706{
707 ALOGV("stopRecognition() model handle %d", handle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700708 if (mHalInterface == 0) {
709 return NO_INIT;
710 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700711 AutoMutex lock(mLock);
712 sp<Model> model = getModel(handle);
713 if (model == 0) {
714 return BAD_VALUE;
715 }
716
717 if (model->mState != Model::STATE_ACTIVE) {
718 return INVALID_OPERATION;
719 }
Eric Laurent7a544b42016-08-05 19:01:13 -0700720 mHalInterface->stopRecognition(handle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700721 model->mState = Model::STATE_IDLE;
722 return NO_ERROR;
723}
724
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700725void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700726{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700727 ALOGV("onCallbackEvent type %d", event->mType);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700728
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700729 sp<IMemory> eventMemory = event->mMemory;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700730
731 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
732 return;
733 }
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700734 if (mModuleClients.isEmpty()) {
735 ALOGI("%s no clients", __func__);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700736 return;
737 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700738
739 switch (event->mType) {
740 case CallbackEvent::TYPE_RECOGNITION: {
741 struct sound_trigger_recognition_event *recognitionEvent =
742 (struct sound_trigger_recognition_event *)eventMemory->pointer();
Eric Laurent886561f2014-08-28 19:45:37 -0700743 sp<ISoundTriggerClient> client;
744 {
745 AutoMutex lock(mLock);
746 sp<Model> model = getModel(recognitionEvent->model);
747 if (model == 0) {
748 ALOGW("%s model == 0", __func__);
749 return;
750 }
751 if (model->mState != Model::STATE_ACTIVE) {
752 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
753 return;
754 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700755
Eric Laurent886561f2014-08-28 19:45:37 -0700756 recognitionEvent->capture_session = model->mCaptureSession;
757 model->mState = Model::STATE_IDLE;
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700758 client = model->mModuleClient->client();
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700759 }
Eric Laurent886561f2014-08-28 19:45:37 -0700760 if (client != 0) {
761 client->onRecognitionEvent(eventMemory);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700762 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700763 } break;
764 case CallbackEvent::TYPE_SOUNDMODEL: {
765 struct sound_trigger_model_event *soundmodelEvent =
766 (struct sound_trigger_model_event *)eventMemory->pointer();
Eric Laurent886561f2014-08-28 19:45:37 -0700767 sp<ISoundTriggerClient> client;
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 }
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700775 client = model->mModuleClient->client();
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700776 }
Eric Laurent886561f2014-08-28 19:45:37 -0700777 if (client != 0) {
778 client->onSoundModelEvent(eventMemory);
779 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700780 } break;
781 case CallbackEvent::TYPE_SERVICE_STATE: {
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700782 Vector< sp<ISoundTriggerClient> > clients;
Eric Laurent886561f2014-08-28 19:45:37 -0700783 {
784 AutoMutex lock(mLock);
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700785 for (size_t i = 0; i < mModuleClients.size(); i++) {
786 if (mModuleClients[i] != 0) {
787 clients.add(mModuleClients[i]->client());
788 }
789 }
Eric Laurent886561f2014-08-28 19:45:37 -0700790 }
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700791 for (size_t i = 0; i < clients.size(); i++) {
792 clients[i]->onServiceStateChange(eventMemory);
Eric Laurent886561f2014-08-28 19:45:37 -0700793 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700794 } break;
795 default:
796 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
797 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700798}
799
800sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
801 sound_model_handle_t handle)
802{
803 sp<Model> model;
804 ssize_t index = mModels.indexOfKey(handle);
805 if (index >= 0) {
806 model = mModels.valueAt(index);
807 }
808 return model;
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
Chris Thorntonefcf16c2016-03-27 17:13:28 -0700839 const bool supports_stop_all =
Eric Laurent7a544b42016-08-05 19:01:13 -0700840 (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() == ENOSYS);
Chris Thorntonefcf16c2016-03-27 17:13:28 -0700841
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700842 for (size_t i = 0; i < mModels.size(); i++) {
843 sp<Model> model = mModels.valueAt(i);
844 if (model->mState == Model::STATE_ACTIVE) {
Eric Laurent7a544b42016-08-05 19:01:13 -0700845 if (mHalInterface != 0 && !supports_stop_all) {
846 mHalInterface->stopRecognition(model->mHandle);
Chris Thorntonefcf16c2016-03-27 17:13:28 -0700847 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700848 // keep model in ACTIVE state so that event is processed by onCallbackEvent()
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800849 if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
850 struct sound_trigger_phrase_recognition_event event;
851 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
852 event.num_phrases = model->mConfig.num_phrases;
853 for (size_t i = 0; i < event.num_phrases; i++) {
854 event.phrase_extras[i] = model->mConfig.phrases[i];
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700855 }
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800856 event.common.status = RECOGNITION_STATUS_ABORT;
857 event.common.type = model->mType;
858 event.common.model = model->mHandle;
859 event.common.data_size = 0;
860 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
861 if (eventMemory != 0) {
862 events.add(eventMemory);
863 }
864 } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
865 struct sound_trigger_generic_recognition_event event;
866 memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
867 event.common.status = RECOGNITION_STATUS_ABORT;
868 event.common.type = model->mType;
869 event.common.model = model->mHandle;
870 event.common.data_size = 0;
871 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
872 if (eventMemory != 0) {
873 events.add(eventMemory);
874 }
Ryan Bavetta9609a912016-01-28 19:22:29 -0800875 } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
876 struct sound_trigger_phrase_recognition_event event;
877 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
878 event.common.status = RECOGNITION_STATUS_ABORT;
879 event.common.type = model->mType;
880 event.common.model = model->mHandle;
881 event.common.data_size = 0;
882 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
883 if (eventMemory != 0) {
884 events.add(eventMemory);
885 }
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800886 } else {
887 goto exit;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700888 }
889 }
890 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700891 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700892
893 for (size_t i = 0; i < events.size(); i++) {
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700894 sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
895 events[i]);
896 callbackEvent->setModule(this);
897 service->sendCallbackEvent_l(callbackEvent);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700898 }
899
900exit:
901 service->sendServiceStateEvent_l(state, this);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700902}
903
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700904
905SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
906 audio_io_handle_t ioHandle, audio_devices_t device,
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700907 sound_trigger_sound_model_type_t type,
908 sp<ModuleClient>& moduleClient) :
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700909 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700910 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type),
911 mModuleClient(moduleClient)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700912{
Eric Laurentb7a11d82014-04-18 17:40:41 -0700913}
914
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700915#undef LOG_TAG
916#define LOG_TAG "SoundTriggerHwService::ModuleClient"
917
918SoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module,
919 const sp<ISoundTriggerClient>& client)
920 : mModule(module), mClient(client)
921{
922}
923
924void SoundTriggerHwService::ModuleClient::onFirstRef()
925{
926 IInterface::asBinder(mClient)->linkToDeath(this);
927}
928
929SoundTriggerHwService::ModuleClient::~ModuleClient()
930{
931}
932
933status_t SoundTriggerHwService::ModuleClient::dump(int fd __unused,
934 const Vector<String16>& args __unused) {
Eric Laurentb7a11d82014-04-18 17:40:41 -0700935 String8 result;
936 return NO_ERROR;
937}
938
Haynes Mathew Georgee52c5002016-10-12 17:27:18 -0700939void SoundTriggerHwService::ModuleClient::detach() {
940 ALOGV("detach()");
941 if (!captureHotwordAllowed()) {
942 return;
943 }
944
945 {
946 AutoMutex lock(mLock);
947 if (mClient != 0) {
948 IInterface::asBinder(mClient)->unlinkToDeath(this);
949 mClient.clear();
950 }
951 }
952
953 sp<Module> module = mModule.promote();
954 if (module == 0) {
955 return;
956 }
957 module->detach(this);
958}
959
960status_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory,
961 sound_model_handle_t *handle)
962{
963 ALOGV("loadSoundModel() handle");
964 if (!captureHotwordAllowed()) {
965 return PERMISSION_DENIED;
966 }
967
968 sp<Module> module = mModule.promote();
969 if (module == 0) {
970 return NO_INIT;
971 }
972 return module->loadSoundModel(modelMemory, this, handle);
973}
974
975status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
976{
977 ALOGV("unloadSoundModel() model handle %d", handle);
978 if (!captureHotwordAllowed()) {
979 return PERMISSION_DENIED;
980 }
981
982 sp<Module> module = mModule.promote();
983 if (module == 0) {
984 return NO_INIT;
985 }
986 return module->unloadSoundModel(handle);
987}
988
989status_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle,
990 const sp<IMemory>& dataMemory)
991{
992 ALOGV("startRecognition() model handle %d", handle);
993 if (!captureHotwordAllowed()) {
994 return PERMISSION_DENIED;
995 }
996
997 sp<Module> module = mModule.promote();
998 if (module == 0) {
999 return NO_INIT;
1000 }
1001 return module->startRecognition(handle, dataMemory);
1002}
1003
1004status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
1005{
1006 ALOGV("stopRecognition() model handle %d", handle);
1007 if (!captureHotwordAllowed()) {
1008 return PERMISSION_DENIED;
1009 }
1010
1011 sp<Module> module = mModule.promote();
1012 if (module == 0) {
1013 return NO_INIT;
1014 }
1015 return module->stopRecognition(handle);
1016}
1017
1018void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
1019{
1020 ALOGV("ModuleClient::setCaptureState_l %d", active);
1021 sp<SoundTriggerHwService> service;
1022 sound_trigger_service_state_t state;
1023
1024 sp<Module> module = mModule.promote();
1025 if (module == 0) {
1026 return;
1027 }
1028 {
1029 AutoMutex lock(mLock);
1030 state = (active && !module->isConcurrentCaptureAllowed()) ?
1031 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
1032
1033 service = module->service().promote();
1034 if (service == 0) {
1035 return;
1036 }
1037 }
1038 service->sendServiceStateEvent_l(state, this);
1039}
1040
1041void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
1042{
1043 ALOGV("ModuleClient onCallbackEvent type %d", event->mType);
1044
1045 sp<IMemory> eventMemory = event->mMemory;
1046
1047 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
1048 return;
1049 }
1050
1051 switch (event->mType) {
1052 case CallbackEvent::TYPE_SERVICE_STATE: {
1053 sp<ISoundTriggerClient> client;
1054 {
1055 AutoMutex lock(mLock);
1056 client = mClient;
1057 }
1058 if (client !=0 ) {
1059 client->onServiceStateChange(eventMemory);
1060 }
1061 } break;
1062 default:
1063 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
1064 }
1065}
1066
1067void SoundTriggerHwService::ModuleClient::binderDied(
1068 const wp<IBinder> &who __unused) {
1069 ALOGW("client binder died for client %p", this);
1070 detach();
1071}
1072
Eric Laurentb7a11d82014-04-18 17:40:41 -07001073}; // namespace android