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