blob: 3ba7f62df1bce3fb883fc134754146c682b982bc [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
76 sp<ISoundTriggerClient> client;
Eric Laurent7a544b42016-08-05 19:01:13 -070077 sp<Module> module = new Module(this, halInterface, descriptor, client);
Eric Laurentb7a11d82014-04-18 17:40:41 -070078 mModules.add(descriptor.handle, module);
79 mCallbackThread = new CallbackThread(this);
80}
81
82SoundTriggerHwService::~SoundTriggerHwService()
83{
84 if (mCallbackThread != 0) {
85 mCallbackThread->exit();
86 }
Eric Laurentb7a11d82014-04-18 17:40:41 -070087}
88
89status_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
90 uint32_t *numModules)
91{
92 ALOGV("listModules");
Eric Laurent8ba53d82014-08-01 23:15:05 +000093 if (!captureHotwordAllowed()) {
94 return PERMISSION_DENIED;
95 }
96
Eric Laurentb7a11d82014-04-18 17:40:41 -070097 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
109status_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);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000114 if (!captureHotwordAllowed()) {
115 return PERMISSION_DENIED;
116 }
117
Eric Laurentb7a11d82014-04-18 17:40:41 -0700118 AutoMutex lock(mServiceLock);
119 moduleInterface.clear();
120 if (client == 0) {
121 return BAD_VALUE;
122 }
123 ssize_t index = mModules.indexOfKey(handle);
124 if (index < 0) {
125 return BAD_VALUE;
126 }
127 sp<Module> module = mModules.valueAt(index);
128
129 module->setClient(client);
Marco Nelissenf8880202014-11-14 07:58:25 -0800130 IInterface::asBinder(client)->linkToDeath(module);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700131 moduleInterface = module;
132
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700133 module->setCaptureState_l(mCaptureState);
134
Eric Laurentb7a11d82014-04-18 17:40:41 -0700135 return NO_ERROR;
136}
137
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700138status_t SoundTriggerHwService::setCaptureState(bool active)
139{
140 ALOGV("setCaptureState %d", active);
141 AutoMutex lock(mServiceLock);
142 mCaptureState = active;
143 for (size_t i = 0; i < mModules.size(); i++) {
144 mModules.valueAt(i)->setCaptureState_l(active);
145 }
146 return NO_ERROR;
147}
148
149
Chih-Hung Hsieh85f8a732016-08-09 14:10:03 -0700150void SoundTriggerHwService::detachModule(const sp<Module>& module)
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700151{
Eric Laurent936c84a2014-07-17 10:26:04 -0700152 ALOGV("detachModule");
Eric Laurent8ba53d82014-08-01 23:15:05 +0000153 AutoMutex lock(mServiceLock);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700154 module->clearClient();
155}
156
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700157
Eric Laurentb7a11d82014-04-18 17:40:41 -0700158static const int kDumpLockRetries = 50;
159static const int kDumpLockSleep = 60000;
160
161static bool tryLock(Mutex& mutex)
162{
163 bool locked = false;
164 for (int i = 0; i < kDumpLockRetries; ++i) {
165 if (mutex.tryLock() == NO_ERROR) {
166 locked = true;
167 break;
168 }
169 usleep(kDumpLockSleep);
170 }
171 return locked;
172}
173
174status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
175 String8 result;
176 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
177 result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
178 write(fd, result.string(), result.size());
179 } else {
180 bool locked = tryLock(mServiceLock);
181 // failed to lock - SoundTriggerHwService is probably deadlocked
182 if (!locked) {
183 result.append("SoundTriggerHwService may be deadlocked\n");
184 write(fd, result.string(), result.size());
185 }
186
187 if (locked) mServiceLock.unlock();
188 }
189 return NO_ERROR;
190}
191
192status_t SoundTriggerHwService::onTransact(
193 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
194 return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
195}
196
197
198// static
199void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
200 void *cookie)
201{
202 Module *module = (Module *)cookie;
203 if (module == NULL) {
204 return;
205 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700206 sp<SoundTriggerHwService> service = module->service().promote();
207 if (service == 0) {
208 return;
209 }
210
211 service->sendRecognitionEvent(event, module);
212}
213
214sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
215 struct sound_trigger_recognition_event *event)
216{
217 sp<IMemory> eventMemory;
218
219 //sanitize event
220 switch (event->type) {
221 case SOUND_MODEL_TYPE_KEYPHRASE:
222 ALOGW_IF(event->data_size != 0 && event->data_offset !=
223 sizeof(struct sound_trigger_phrase_recognition_event),
224 "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
225 event->data_offset);
226 event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
227 break;
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800228 case SOUND_MODEL_TYPE_GENERIC:
229 ALOGW_IF(event->data_size != 0 && event->data_offset !=
230 sizeof(struct sound_trigger_generic_recognition_event),
231 "prepareRecognitionEvent_l(): invalid data offset %u for generic event type",
232 event->data_offset);
233 event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
234 break;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700235 case SOUND_MODEL_TYPE_UNKNOWN:
236 ALOGW_IF(event->data_size != 0 && event->data_offset !=
237 sizeof(struct sound_trigger_recognition_event),
238 "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
239 event->data_offset);
240 event->data_offset = sizeof(struct sound_trigger_recognition_event);
241 break;
242 default:
Eric Laurent886561f2014-08-28 19:45:37 -0700243 return eventMemory;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700244 }
245
246 size_t size = event->data_offset + event->data_size;
247 eventMemory = mMemoryDealer->allocate(size);
248 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
249 eventMemory.clear();
250 return eventMemory;
251 }
252 memcpy(eventMemory->pointer(), event, size);
253
254 return eventMemory;
255}
256
257void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
258 Module *module)
259 {
260 AutoMutex lock(mServiceLock);
261 if (module == NULL) {
262 return;
263 }
264 sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
265 if (eventMemory == 0) {
266 return;
267 }
268 sp<Module> strongModule;
269 for (size_t i = 0; i < mModules.size(); i++) {
270 if (mModules.valueAt(i).get() == module) {
271 strongModule = mModules.valueAt(i);
272 break;
273 }
274 }
275 if (strongModule == 0) {
276 return;
277 }
278
279 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
280 eventMemory, strongModule));
281}
282
283// static
284void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
285 void *cookie)
286{
287 Module *module = (Module *)cookie;
288 if (module == NULL) {
289 return;
290 }
291 sp<SoundTriggerHwService> service = module->service().promote();
292 if (service == 0) {
293 return;
294 }
295
296 service->sendSoundModelEvent(event, module);
297}
298
299sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
300{
301 sp<IMemory> eventMemory;
302
303 size_t size = event->data_offset + event->data_size;
304 eventMemory = mMemoryDealer->allocate(size);
305 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
306 eventMemory.clear();
307 return eventMemory;
308 }
309 memcpy(eventMemory->pointer(), event, size);
310
311 return eventMemory;
312}
313
314void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
315 Module *module)
316{
317 AutoMutex lock(mServiceLock);
318 sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
319 if (eventMemory == 0) {
320 return;
321 }
322 sp<Module> strongModule;
323 for (size_t i = 0; i < mModules.size(); i++) {
324 if (mModules.valueAt(i).get() == module) {
325 strongModule = mModules.valueAt(i);
326 break;
327 }
328 }
329 if (strongModule == 0) {
330 return;
331 }
332 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
333 eventMemory, strongModule));
Eric Laurentb7a11d82014-04-18 17:40:41 -0700334}
335
336
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700337sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700338{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700339 sp<IMemory> eventMemory;
340
341 size_t size = sizeof(sound_trigger_service_state_t);
342 eventMemory = mMemoryDealer->allocate(size);
343 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
344 eventMemory.clear();
345 return eventMemory;
346 }
347 *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
348 return eventMemory;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700349}
350
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700351// call with mServiceLock held
352void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
353 Module *module)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700354{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700355 sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
356 if (eventMemory == 0) {
357 return;
358 }
359 sp<Module> strongModule;
360 for (size_t i = 0; i < mModules.size(); i++) {
361 if (mModules.valueAt(i).get() == module) {
362 strongModule = mModules.valueAt(i);
363 break;
364 }
365 }
366 if (strongModule == 0) {
367 return;
368 }
369 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
370 eventMemory, strongModule));
371}
372
373// call with mServiceLock held
374void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
375{
376 mCallbackThread->sendCallbackEvent(event);
377}
378
379void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
380{
381 ALOGV("onCallbackEvent");
Eric Laurentb7a11d82014-04-18 17:40:41 -0700382 sp<Module> module;
383 {
384 AutoMutex lock(mServiceLock);
385 module = event->mModule.promote();
386 if (module == 0) {
387 return;
388 }
389 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700390 module->onCallbackEvent(event);
391 {
392 AutoMutex lock(mServiceLock);
393 // clear now to execute with mServiceLock locked
394 event->mMemory.clear();
395 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700396}
397
398#undef LOG_TAG
399#define LOG_TAG "SoundTriggerHwService::CallbackThread"
400
401SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
402 : mService(service)
403{
404}
405
406SoundTriggerHwService::CallbackThread::~CallbackThread()
407{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700408 while (!mEventQueue.isEmpty()) {
409 mEventQueue[0]->mMemory.clear();
410 mEventQueue.removeAt(0);
411 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700412}
413
414void SoundTriggerHwService::CallbackThread::onFirstRef()
415{
416 run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
417}
418
419bool SoundTriggerHwService::CallbackThread::threadLoop()
420{
421 while (!exitPending()) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700422 sp<CallbackEvent> event;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700423 sp<SoundTriggerHwService> service;
424 {
425 Mutex::Autolock _l(mCallbackLock);
426 while (mEventQueue.isEmpty() && !exitPending()) {
427 ALOGV("CallbackThread::threadLoop() sleep");
428 mCallbackCond.wait(mCallbackLock);
429 ALOGV("CallbackThread::threadLoop() wake up");
430 }
431 if (exitPending()) {
432 break;
433 }
434 event = mEventQueue[0];
435 mEventQueue.removeAt(0);
436 service = mService.promote();
437 }
438 if (service != 0) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700439 service->onCallbackEvent(event);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700440 }
441 }
442 return false;
443}
444
445void SoundTriggerHwService::CallbackThread::exit()
446{
447 Mutex::Autolock _l(mCallbackLock);
448 requestExit();
449 mCallbackCond.broadcast();
450}
451
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700452void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
453 const sp<SoundTriggerHwService::CallbackEvent>& event)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700454{
455 AutoMutex lock(mCallbackLock);
456 mEventQueue.add(event);
457 mCallbackCond.signal();
458}
459
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700460SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory,
461 wp<Module> module)
462 : mType(type), mMemory(memory), mModule(module)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700463{
464}
465
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700466SoundTriggerHwService::CallbackEvent::~CallbackEvent()
Eric Laurentb7a11d82014-04-18 17:40:41 -0700467{
468}
469
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700470
Eric Laurentb7a11d82014-04-18 17:40:41 -0700471#undef LOG_TAG
472#define LOG_TAG "SoundTriggerHwService::Module"
473
474SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
Eric Laurent7a544b42016-08-05 19:01:13 -0700475 const sp<SoundTriggerHalInterface>& halInterface,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700476 sound_trigger_module_descriptor descriptor,
477 const sp<ISoundTriggerClient>& client)
Eric Laurent7a544b42016-08-05 19:01:13 -0700478 : mService(service), mHalInterface(halInterface), mDescriptor(descriptor),
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700479 mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700480{
481}
482
483SoundTriggerHwService::Module::~Module() {
484}
485
486void SoundTriggerHwService::Module::detach() {
487 ALOGV("detach()");
Eric Laurent8ba53d82014-08-01 23:15:05 +0000488 if (!captureHotwordAllowed()) {
489 return;
490 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700491 {
492 AutoMutex lock(mLock);
493 for (size_t i = 0; i < mModels.size(); i++) {
494 sp<Model> model = mModels.valueAt(i);
495 ALOGV("detach() unloading model %d", model->mHandle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700496 if (mHalInterface != 0) {
497 if (model->mState == Model::STATE_ACTIVE) {
498 mHalInterface->stopRecognition(model->mHandle);
499 }
500 mHalInterface->unloadSoundModel(model->mHandle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700501 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700502 }
503 mModels.clear();
504 }
505 if (mClient != 0) {
Marco Nelissenf8880202014-11-14 07:58:25 -0800506 IInterface::asBinder(mClient)->unlinkToDeath(this);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700507 }
508 sp<SoundTriggerHwService> service = mService.promote();
509 if (service == 0) {
510 return;
511 }
512 service->detachModule(this);
513}
514
515status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
516 sound_model_handle_t *handle)
517{
518 ALOGV("loadSoundModel() handle");
Eric Laurent7a544b42016-08-05 19:01:13 -0700519 if (mHalInterface == 0) {
520 return NO_INIT;
521 }
Eric Laurent8ba53d82014-08-01 23:15:05 +0000522 if (!captureHotwordAllowed()) {
523 return PERMISSION_DENIED;
524 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700525 if (modelMemory == 0 || modelMemory->pointer() == NULL) {
526 ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
527 return BAD_VALUE;
528 }
529 struct sound_trigger_sound_model *sound_model =
530 (struct sound_trigger_sound_model *)modelMemory->pointer();
531
Eric Laurentbb00d8f2016-08-17 06:19:32 -0700532 size_t structSize;
533 if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
534 structSize = sizeof(struct sound_trigger_phrase_sound_model);
535 } else {
536 structSize = sizeof(struct sound_trigger_sound_model);
537 }
538
539 if (sound_model->data_offset < structSize ||
540 sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
541 modelMemory->size() < sound_model->data_offset ||
542 sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
543 android_errorWriteLog(0x534e4554, "30148546");
544 ALOGE("loadSoundModel() data_size is too big");
545 return BAD_VALUE;
546 }
547
Eric Laurentb7a11d82014-04-18 17:40:41 -0700548 AutoMutex lock(mLock);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800549
550 if (mModels.size() >= mDescriptor.properties.max_sound_models) {
Ryan Bavettaad658992016-04-11 14:25:21 -0700551 ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
552 mDescriptor.properties.max_sound_models);
553 return INVALID_OPERATION;
Eric Laurent02eb47c2014-11-20 10:10:20 -0800554 }
555
Eric Laurent7a544b42016-08-05 19:01:13 -0700556 status_t status = mHalInterface->loadSoundModel(sound_model,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700557 SoundTriggerHwService::soundModelCallback,
Ryan Bavetta2c561202016-02-16 14:17:31 -0800558 this, handle);
559
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700560 if (status != NO_ERROR) {
561 return status;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700562 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700563 audio_session_t session;
564 audio_io_handle_t ioHandle;
565 audio_devices_t device;
566
567 status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
568 if (status != NO_ERROR) {
569 return status;
570 }
571
572 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type);
573 mModels.replaceValueFor(*handle, model);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700574
575 return status;
576}
577
578status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
579{
580 ALOGV("unloadSoundModel() model handle %d", handle);
Eric Laurent8ba53d82014-08-01 23:15:05 +0000581 if (!captureHotwordAllowed()) {
582 return PERMISSION_DENIED;
583 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700584
585 AutoMutex lock(mLock);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800586 return unloadSoundModel_l(handle);
587}
588
589status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
590{
Eric Laurent7a544b42016-08-05 19:01:13 -0700591 if (mHalInterface == 0) {
592 return NO_INIT;
593 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700594 ssize_t index = mModels.indexOfKey(handle);
595 if (index < 0) {
596 return BAD_VALUE;
597 }
Eric Laurent1a1cba82014-06-09 16:20:05 -0700598 sp<Model> model = mModels.valueAt(index);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700599 mModels.removeItem(handle);
Eric Laurent1a1cba82014-06-09 16:20:05 -0700600 if (model->mState == Model::STATE_ACTIVE) {
Eric Laurent7a544b42016-08-05 19:01:13 -0700601 mHalInterface->stopRecognition(model->mHandle);
Eric Laurent02eb47c2014-11-20 10:10:20 -0800602 model->mState = Model::STATE_IDLE;
Eric Laurent1a1cba82014-06-09 16:20:05 -0700603 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700604 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
Eric Laurent7a544b42016-08-05 19:01:13 -0700605 return mHalInterface->unloadSoundModel(handle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700606}
607
608status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
Eric Laurent0832b2d2014-07-06 16:17:25 -0700609 const sp<IMemory>& dataMemory)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700610{
611 ALOGV("startRecognition() model handle %d", handle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700612 if (mHalInterface == 0) {
613 return NO_INIT;
614 }
Eric Laurent8ba53d82014-08-01 23:15:05 +0000615 if (!captureHotwordAllowed()) {
616 return PERMISSION_DENIED;
617 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700618
Eric Laurentbb00d8f2016-08-17 06:19:32 -0700619 if (dataMemory == 0 || dataMemory->pointer() == NULL) {
620 ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
Eric Laurentb7a11d82014-04-18 17:40:41 -0700621 return BAD_VALUE;
622
623 }
Eric Laurentbb00d8f2016-08-17 06:19:32 -0700624
625 struct sound_trigger_recognition_config *config =
626 (struct sound_trigger_recognition_config *)dataMemory->pointer();
627
628 if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
629 config->data_size > (UINT_MAX - config->data_offset) ||
630 dataMemory->size() < config->data_offset ||
631 config->data_size > (dataMemory->size() - config->data_offset)) {
632 ALOGE("startRecognition() data_size is too big");
633 return BAD_VALUE;
634 }
635
Eric Laurentb7a11d82014-04-18 17:40:41 -0700636 AutoMutex lock(mLock);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700637 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
638 return INVALID_OPERATION;
639 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700640 sp<Model> model = getModel(handle);
641 if (model == 0) {
642 return BAD_VALUE;
643 }
644
645 if (model->mState == Model::STATE_ACTIVE) {
646 return INVALID_OPERATION;
647 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700648
Eric Laurentb7a11d82014-04-18 17:40:41 -0700649
650 //TODO: get capture handle and device from audio policy service
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700651 config->capture_handle = model->mCaptureIOHandle;
652 config->capture_device = model->mCaptureDevice;
Eric Laurent7a544b42016-08-05 19:01:13 -0700653 status_t status = mHalInterface->startRecognition(handle, config,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700654 SoundTriggerHwService::recognitionCallback,
Eric Laurent0832b2d2014-07-06 16:17:25 -0700655 this);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700656
657 if (status == NO_ERROR) {
658 model->mState = Model::STATE_ACTIVE;
659 model->mConfig = *config;
660 }
661
662 return status;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700663}
664
665status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
666{
667 ALOGV("stopRecognition() model handle %d", handle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700668 if (mHalInterface == 0) {
669 return NO_INIT;
670 }
Eric Laurent8ba53d82014-08-01 23:15:05 +0000671 if (!captureHotwordAllowed()) {
672 return PERMISSION_DENIED;
673 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700674
675 AutoMutex lock(mLock);
676 sp<Model> model = getModel(handle);
677 if (model == 0) {
678 return BAD_VALUE;
679 }
680
681 if (model->mState != Model::STATE_ACTIVE) {
682 return INVALID_OPERATION;
683 }
Eric Laurent7a544b42016-08-05 19:01:13 -0700684 mHalInterface->stopRecognition(handle);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700685 model->mState = Model::STATE_IDLE;
686 return NO_ERROR;
687}
688
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700689
690void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700691{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700692 ALOGV("onCallbackEvent type %d", event->mType);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700693
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700694 sp<IMemory> eventMemory = event->mMemory;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700695
696 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
697 return;
698 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700699 if (mClient == 0) {
700 ALOGI("%s mClient == 0", __func__);
701 return;
702 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700703
704 switch (event->mType) {
705 case CallbackEvent::TYPE_RECOGNITION: {
706 struct sound_trigger_recognition_event *recognitionEvent =
707 (struct sound_trigger_recognition_event *)eventMemory->pointer();
Eric Laurent886561f2014-08-28 19:45:37 -0700708 sp<ISoundTriggerClient> client;
709 {
710 AutoMutex lock(mLock);
711 sp<Model> model = getModel(recognitionEvent->model);
712 if (model == 0) {
713 ALOGW("%s model == 0", __func__);
714 return;
715 }
716 if (model->mState != Model::STATE_ACTIVE) {
717 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
718 return;
719 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700720
Eric Laurent886561f2014-08-28 19:45:37 -0700721 recognitionEvent->capture_session = model->mCaptureSession;
722 model->mState = Model::STATE_IDLE;
723 client = mClient;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700724 }
Eric Laurent886561f2014-08-28 19:45:37 -0700725 if (client != 0) {
726 client->onRecognitionEvent(eventMemory);
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700727 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700728 } break;
729 case CallbackEvent::TYPE_SOUNDMODEL: {
730 struct sound_trigger_model_event *soundmodelEvent =
731 (struct sound_trigger_model_event *)eventMemory->pointer();
Eric Laurent886561f2014-08-28 19:45:37 -0700732 sp<ISoundTriggerClient> client;
733 {
734 AutoMutex lock(mLock);
735 sp<Model> model = getModel(soundmodelEvent->model);
736 if (model == 0) {
737 ALOGW("%s model == 0", __func__);
738 return;
739 }
740 client = mClient;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700741 }
Eric Laurent886561f2014-08-28 19:45:37 -0700742 if (client != 0) {
743 client->onSoundModelEvent(eventMemory);
744 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700745 } break;
746 case CallbackEvent::TYPE_SERVICE_STATE: {
Eric Laurent886561f2014-08-28 19:45:37 -0700747 sp<ISoundTriggerClient> client;
748 {
749 AutoMutex lock(mLock);
750 client = mClient;
751 }
752 if (client != 0) {
753 client->onServiceStateChange(eventMemory);
754 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700755 } break;
756 default:
757 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
758 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700759}
760
761sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
762 sound_model_handle_t handle)
763{
764 sp<Model> model;
765 ssize_t index = mModels.indexOfKey(handle);
766 if (index >= 0) {
767 model = mModels.valueAt(index);
768 }
769 return model;
770}
771
772void SoundTriggerHwService::Module::binderDied(
773 const wp<IBinder> &who __unused) {
774 ALOGW("client binder died for module %d", mDescriptor.handle);
775 detach();
776}
777
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700778// Called with mServiceLock held
779void SoundTriggerHwService::Module::setCaptureState_l(bool active)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700780{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700781 ALOGV("Module::setCaptureState_l %d", active);
782 sp<SoundTriggerHwService> service;
783 sound_trigger_service_state_t state;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700784
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700785 Vector< sp<IMemory> > events;
786 {
787 AutoMutex lock(mLock);
788 state = (active && !mDescriptor.properties.concurrent_capture) ?
789 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
Eric Laurentb7a11d82014-04-18 17:40:41 -0700790
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700791 if (state == mServiceState) {
792 return;
793 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700794
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700795 mServiceState = state;
796
797 service = mService.promote();
798 if (service == 0) {
799 return;
800 }
801
802 if (state == SOUND_TRIGGER_STATE_ENABLED) {
803 goto exit;
804 }
805
Chris Thorntonefcf16c2016-03-27 17:13:28 -0700806 const bool supports_stop_all =
Eric Laurent7a544b42016-08-05 19:01:13 -0700807 (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() == ENOSYS);
Chris Thorntonefcf16c2016-03-27 17:13:28 -0700808
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700809 for (size_t i = 0; i < mModels.size(); i++) {
810 sp<Model> model = mModels.valueAt(i);
811 if (model->mState == Model::STATE_ACTIVE) {
Eric Laurent7a544b42016-08-05 19:01:13 -0700812 if (mHalInterface != 0 && !supports_stop_all) {
813 mHalInterface->stopRecognition(model->mHandle);
Chris Thorntonefcf16c2016-03-27 17:13:28 -0700814 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700815 // keep model in ACTIVE state so that event is processed by onCallbackEvent()
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800816 if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
817 struct sound_trigger_phrase_recognition_event event;
818 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
819 event.num_phrases = model->mConfig.num_phrases;
820 for (size_t i = 0; i < event.num_phrases; i++) {
821 event.phrase_extras[i] = model->mConfig.phrases[i];
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700822 }
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800823 event.common.status = RECOGNITION_STATUS_ABORT;
824 event.common.type = model->mType;
825 event.common.model = model->mHandle;
826 event.common.data_size = 0;
827 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
828 if (eventMemory != 0) {
829 events.add(eventMemory);
830 }
831 } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
832 struct sound_trigger_generic_recognition_event event;
833 memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
834 event.common.status = RECOGNITION_STATUS_ABORT;
835 event.common.type = model->mType;
836 event.common.model = model->mHandle;
837 event.common.data_size = 0;
838 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
839 if (eventMemory != 0) {
840 events.add(eventMemory);
841 }
Ryan Bavetta9609a912016-01-28 19:22:29 -0800842 } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
843 struct sound_trigger_phrase_recognition_event event;
844 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
845 event.common.status = RECOGNITION_STATUS_ABORT;
846 event.common.type = model->mType;
847 event.common.model = model->mHandle;
848 event.common.data_size = 0;
849 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
850 if (eventMemory != 0) {
851 events.add(eventMemory);
852 }
Ryan Bavetta00a727c2016-01-26 21:56:19 -0800853 } else {
854 goto exit;
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700855 }
856 }
857 }
Eric Laurentb7a11d82014-04-18 17:40:41 -0700858 }
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700859
860 for (size_t i = 0; i < events.size(); i++) {
861 service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i],
862 this));
863 }
864
865exit:
866 service->sendServiceStateEvent_l(state, this);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700867}
868
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700869
870SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
871 audio_io_handle_t ioHandle, audio_devices_t device,
872 sound_trigger_sound_model_type_t type) :
873 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
874 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700875{
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700876
Eric Laurentb7a11d82014-04-18 17:40:41 -0700877}
878
879status_t SoundTriggerHwService::Module::dump(int fd __unused,
880 const Vector<String16>& args __unused) {
881 String8 result;
882 return NO_ERROR;
883}
884
885}; // namespace android