1 /*
2  * Copyright (C) 2019 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 #define LOG_TAG "SoundTriggerHw"
17 
18 #include "SoundTriggerHw.h"
19 
20 #include <android/hidl/allocator/1.0/IAllocator.h>
21 #include <android/log.h>
22 #include <hidlmemory/mapping.h>
23 #include <utility>
24 
25 using android::hardware::hidl_memory;
26 using android::hidl::allocator::V1_0::IAllocator;
27 using android::hidl::memory::V1_0::IMemory;
28 
29 namespace android {
30 namespace hardware {
31 namespace soundtrigger {
32 namespace V2_3 {
33 namespace implementation {
34 
35 /**
36  * According to the HIDL C++ Users Guide: client and server implementations
37  * should never directly refer to anything other than the interface header
38  * generated from the HIDL definition file (ie. ISoundTriggerHw.hal), so
39  * this V2_3 implementation copies the previous implementations and
40  * then adds the new implementation.
41  */
42 
43 // Begin V2_0 implementation, copied from
44 // hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
45 
46 // static
soundModelCallback_(struct sound_trigger_model_event * halEvent,void * cookie)47 void soundModelCallback_(struct sound_trigger_model_event* halEvent, void* cookie) {
48     if (halEvent == NULL) {
49         ALOGW("soundModelCallback called with NULL event");
50         return;
51     }
52     sp<SoundTriggerHw::SoundModelClient> client =
53             wp<SoundTriggerHw::SoundModelClient>(
54                     static_cast<SoundTriggerHw::SoundModelClient*>(cookie))
55                     .promote();
56     if (client == 0) {
57         ALOGW("soundModelCallback called on stale client");
58         return;
59     }
60     if (halEvent->model != client->getHalHandle()) {
61         ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
62               (int)halEvent->model, (int)client->getHalHandle());
63         return;
64     }
65 
66     client->soundModelCallback(halEvent);
67 }
68 
69 // static
recognitionCallback_(struct sound_trigger_recognition_event * halEvent,void * cookie)70 void recognitionCallback_(struct sound_trigger_recognition_event* halEvent, void* cookie) {
71     if (halEvent == NULL) {
72         ALOGW("recognitionCallback call NULL event");
73         return;
74     }
75     sp<SoundTriggerHw::SoundModelClient> client =
76             wp<SoundTriggerHw::SoundModelClient>(
77                     static_cast<SoundTriggerHw::SoundModelClient*>(cookie))
78                     .promote();
79     if (client == 0) {
80         ALOGW("recognitionCallback called on stale client");
81         return;
82     }
83 
84     client->recognitionCallback(halEvent);
85 }
86 
getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb)87 Return<void> SoundTriggerHw::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) {
88     ALOGV("getProperties() mHwDevice %p", mHwDevice);
89     int ret;
90     struct sound_trigger_properties halProperties;
91     V2_0::ISoundTriggerHw::Properties properties;
92 
93     if (mHwDevice == NULL) {
94         ret = -ENODEV;
95         goto exit;
96     }
97 
98     ret = mHwDevice->get_properties(mHwDevice, &halProperties);
99 
100     convertPropertiesFromHal(&properties, &halProperties);
101 
102     ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
103           properties.recognitionModes);
104 
105 exit:
106     _hidl_cb(ret, properties);
107     return Void();
108 }
109 
doLoadSoundModel(const V2_0::ISoundTriggerHw::SoundModel & soundModel,sp<SoundTriggerHw::SoundModelClient> client)110 int SoundTriggerHw::doLoadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
111                                      sp<SoundTriggerHw::SoundModelClient> client) {
112     int32_t ret = 0;
113     struct sound_trigger_sound_model* halSoundModel;
114 
115     ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
116 
117     if (mHwDevice == NULL) {
118         ret = -ENODEV;
119         goto exit;
120     }
121 
122     halSoundModel = convertSoundModelToHal(&soundModel);
123     if (halSoundModel == NULL) {
124         ret = -EINVAL;
125         goto exit;
126     }
127 
128     sound_model_handle_t halHandle;
129     ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback_, client.get(),
130                                       &halHandle);
131 
132     free(halSoundModel);
133 
134     if (ret != 0) {
135         goto exit;
136     }
137 
138     client->setHalHandle(halHandle);
139     {
140         AutoMutex lock(mLock);
141         mClients.add(client->getId(), client);
142     }
143 
144 exit:
145     return ret;
146 }
147 
loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel & soundModel,const sp<V2_0::ISoundTriggerHwCallback> & callback,V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,ISoundTriggerHw::loadSoundModel_cb _hidl_cb)148 Return<void> SoundTriggerHw::loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
149                                             const sp<V2_0::ISoundTriggerHwCallback>& callback,
150                                             V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
151                                             ISoundTriggerHw::loadSoundModel_cb _hidl_cb) {
152     sp<SoundTriggerHw::SoundModelClient> client =
153             new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
154     _hidl_cb(doLoadSoundModel(soundModel, client), client->getId());
155     return Void();
156 }
157 
loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel & soundModel,const sp<V2_0::ISoundTriggerHwCallback> & callback,V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb)158 Return<void> SoundTriggerHw::loadPhraseSoundModel(
159         const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel,
160         const sp<V2_0::ISoundTriggerHwCallback>& callback,
161         V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
162         ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
163     sp<SoundTriggerHw::SoundModelClient> client =
164             new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
165     _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel, client),
166              client->getId());
167     return Void();
168 }
169 
unloadSoundModel(int32_t modelHandle)170 Return<int32_t> SoundTriggerHw::unloadSoundModel(int32_t modelHandle) {
171     int32_t ret;
172     sp<SoundTriggerHw::SoundModelClient> client;
173 
174     if (mHwDevice == NULL) {
175         ret = -ENODEV;
176         goto exit;
177     }
178 
179     {
180         AutoMutex lock(mLock);
181         client = mClients.valueFor(modelHandle);
182         if (client == 0) {
183             ret = -ENOSYS;
184             goto exit;
185         }
186     }
187 
188     ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle());
189 
190     mClients.removeItem(modelHandle);
191 
192 exit:
193     return ret;
194 }
195 
startRecognition(int32_t modelHandle,const V2_0::ISoundTriggerHw::RecognitionConfig & config,const sp<V2_0::ISoundTriggerHwCallback> &,int32_t)196 Return<int32_t> SoundTriggerHw::startRecognition(
197         int32_t modelHandle, const V2_0::ISoundTriggerHw::RecognitionConfig& config,
198         const sp<V2_0::ISoundTriggerHwCallback>& /* callback */, int32_t /* cookie */) {
199     int32_t ret;
200     sp<SoundTriggerHw::SoundModelClient> client;
201     struct sound_trigger_recognition_config* halConfig;
202 
203     if (mHwDevice == NULL) {
204         ret = -ENODEV;
205         goto exit;
206     }
207 
208     {
209         AutoMutex lock(mLock);
210         client = mClients.valueFor(modelHandle);
211         if (client == 0) {
212             ret = -ENOSYS;
213             goto exit;
214         }
215     }
216 
217     halConfig =
218             convertRecognitionConfigToHal((const V2_0::ISoundTriggerHw::RecognitionConfig*)&config);
219 
220     if (halConfig == NULL) {
221         ret = -EINVAL;
222         goto exit;
223     }
224     ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig,
225                                        recognitionCallback_, client.get());
226 
227     free(halConfig);
228 
229 exit:
230     return ret;
231 }
232 
stopRecognition(int32_t modelHandle)233 Return<int32_t> SoundTriggerHw::stopRecognition(int32_t modelHandle) {
234     int32_t ret;
235     sp<SoundTriggerHw::SoundModelClient> client;
236     if (mHwDevice == NULL) {
237         ret = -ENODEV;
238         goto exit;
239     }
240 
241     {
242         AutoMutex lock(mLock);
243         client = mClients.valueFor(modelHandle);
244         if (client == 0) {
245             ret = -ENOSYS;
246             goto exit;
247         }
248     }
249 
250     ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle());
251 
252 exit:
253     return ret;
254 }
255 
stopAllRecognitions()256 Return<int32_t> SoundTriggerHw::stopAllRecognitions() {
257     int32_t ret;
258     if (mHwDevice == NULL) {
259         ret = -ENODEV;
260         goto exit;
261     }
262 
263     ret = mHwDevice->stop_all_recognitions(mHwDevice);
264 
265 exit:
266     return ret;
267 }
268 
SoundTriggerHw()269 SoundTriggerHw::SoundTriggerHw() : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
270 
onFirstRef()271 void SoundTriggerHw::onFirstRef() {
272     const hw_module_t* mod;
273     int rc;
274 
275     rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
276     if (rc != 0) {
277         ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
278               mModuleName, strerror(-rc));
279         return;
280     }
281     rc = sound_trigger_hw_device_open(mod, &mHwDevice);
282     if (rc != 0) {
283         ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
284               SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
285         mHwDevice = NULL;
286         return;
287     }
288     if (mHwDevice->common.version != SOUND_TRIGGER_DEVICE_API_VERSION_1_3) {
289         ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
290         sound_trigger_hw_device_close(mHwDevice);
291         mHwDevice = NULL;
292         return;
293     }
294 
295     ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
296 }
297 
~SoundTriggerHw()298 SoundTriggerHw::~SoundTriggerHw() {
299     if (mHwDevice != NULL) {
300         sound_trigger_hw_device_close(mHwDevice);
301     }
302 }
303 
nextUniqueModelId()304 uint32_t SoundTriggerHw::nextUniqueModelId() {
305     uint32_t modelId = 0;
306     {
307         AutoMutex lock(mLock);
308         do {
309             modelId = atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1,
310                                                 memory_order_acq_rel);
311         } while (mClients.valueFor(modelId) != 0 && modelId != 0);
312     }
313     LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
314                         mClients.size());
315     return modelId;
316 }
317 
convertUuidFromHal(Uuid * uuid,const sound_trigger_uuid_t * halUuid)318 void SoundTriggerHw::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
319     uuid->timeLow = halUuid->timeLow;
320     uuid->timeMid = halUuid->timeMid;
321     uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
322     uuid->variantAndClockSeqHigh = halUuid->clockSeq;
323     memcpy(&uuid->node[0], &halUuid->node[0], 6);
324 }
325 
convertUuidToHal(sound_trigger_uuid_t * halUuid,const Uuid * uuid)326 void SoundTriggerHw::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
327     halUuid->timeLow = uuid->timeLow;
328     halUuid->timeMid = uuid->timeMid;
329     halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
330     halUuid->clockSeq = uuid->variantAndClockSeqHigh;
331     memcpy(&halUuid->node[0], &uuid->node[0], 6);
332 }
333 
convertPropertiesFromHal(V2_0::ISoundTriggerHw::Properties * properties,const struct sound_trigger_properties * halProperties)334 void SoundTriggerHw::convertPropertiesFromHal(
335         V2_0::ISoundTriggerHw::Properties* properties,
336         const struct sound_trigger_properties* halProperties) {
337     properties->implementor = halProperties->implementor;
338     properties->description = halProperties->description;
339     properties->version = halProperties->version;
340     convertUuidFromHal(&properties->uuid, &halProperties->uuid);
341     properties->maxSoundModels = halProperties->max_sound_models;
342     properties->maxKeyPhrases = halProperties->max_key_phrases;
343     properties->maxUsers = halProperties->max_users;
344     properties->recognitionModes = halProperties->recognition_modes;
345     properties->captureTransition = halProperties->capture_transition;
346     properties->maxBufferMs = halProperties->max_buffer_ms;
347     properties->concurrentCapture = halProperties->concurrent_capture;
348     properties->triggerInEvent = halProperties->trigger_in_event;
349     properties->powerConsumptionMw = halProperties->power_consumption_mw;
350 }
351 
convertPropertiesFromHal(V2_3::Properties * properties,const struct sound_trigger_properties_header * header)352 void SoundTriggerHw::convertPropertiesFromHal(
353         V2_3::Properties* properties, const struct sound_trigger_properties_header* header) {
354     if (header->version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_3) {
355         const struct sound_trigger_properties_extended_1_3* halProperties =
356                 (const struct sound_trigger_properties_extended_1_3*)header;
357         convertPropertiesFromHal(&properties->base, &halProperties->base);
358         properties->supportedModelArch = halProperties->supported_model_arch;
359         properties->audioCapabilities = halProperties->audio_capabilities;
360     }
361 }
362 
convertTriggerPhraseToHal(struct sound_trigger_phrase * halTriggerPhrase,const ISoundTriggerHw::Phrase * triggerPhrase)363 void SoundTriggerHw::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
364                                                const ISoundTriggerHw::Phrase* triggerPhrase) {
365     halTriggerPhrase->id = triggerPhrase->id;
366     halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
367     unsigned int i;
368 
369     halTriggerPhrase->num_users =
370             std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS);
371     for (i = 0; i < halTriggerPhrase->num_users; i++) {
372         halTriggerPhrase->users[i] = triggerPhrase->users[i];
373     }
374 
375     strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
376     strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
377 }
378 
convertSoundModelToHal(const V2_0::ISoundTriggerHw::SoundModel * soundModel)379 struct sound_trigger_sound_model* SoundTriggerHw::convertSoundModelToHal(
380         const V2_0::ISoundTriggerHw::SoundModel* soundModel) {
381     struct sound_trigger_sound_model* halModel = NULL;
382     if (soundModel->type == V2_0::SoundModelType::KEYPHRASE) {
383         size_t allocSize =
384                 sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
385         struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
386                 static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
387         LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
388                             "malloc failed for size %zu in convertSoundModelToHal PHRASE",
389                             allocSize);
390 
391         const V2_0::ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
392                 reinterpret_cast<const V2_0::ISoundTriggerHw::PhraseSoundModel*>(soundModel);
393 
394         size_t i;
395         for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
396             convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
397         }
398         halKeyPhraseModel->num_phrases = (unsigned int)i;
399         halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
400         halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
401     } else {
402         size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
403         halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
404         LOG_ALWAYS_FATAL_IF(halModel == NULL,
405                             "malloc failed for size %zu in convertSoundModelToHal GENERIC",
406                             allocSize);
407 
408         halModel->data_offset = sizeof(struct sound_trigger_sound_model);
409     }
410     halModel->type = (sound_trigger_sound_model_type_t)soundModel->type;
411     convertUuidToHal(&halModel->uuid, &soundModel->uuid);
412     convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
413     halModel->data_size = soundModel->data.size();
414     uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
415     const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
416     memcpy(dst, src, soundModel->data.size());
417 
418     return halModel;
419 }
420 
convertPhraseRecognitionExtraToHal(struct sound_trigger_phrase_recognition_extra * halExtra,const V2_0::PhraseRecognitionExtra * extra)421 void SoundTriggerHw::convertPhraseRecognitionExtraToHal(
422         struct sound_trigger_phrase_recognition_extra* halExtra,
423         const V2_0::PhraseRecognitionExtra* extra) {
424     halExtra->id = extra->id;
425     halExtra->recognition_modes = extra->recognitionModes;
426     halExtra->confidence_level = extra->confidenceLevel;
427 
428     unsigned int i;
429     for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
430         halExtra->levels[i].user_id = extra->levels[i].userId;
431         halExtra->levels[i].level = extra->levels[i].levelPercent;
432     }
433     halExtra->num_levels = i;
434 }
435 
convertRecognitionConfigToHal(const V2_0::ISoundTriggerHw::RecognitionConfig * config)436 struct sound_trigger_recognition_config* SoundTriggerHw::convertRecognitionConfigToHal(
437         const V2_0::ISoundTriggerHw::RecognitionConfig* config) {
438     size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
439     struct sound_trigger_recognition_config* halConfig =
440             static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
441 
442     LOG_ALWAYS_FATAL_IF(halConfig == NULL,
443                         "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
444 
445     halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
446     halConfig->capture_device = (audio_devices_t)config->captureDevice;
447     halConfig->capture_requested = config->captureRequested;
448 
449     unsigned int i;
450     for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
451         convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
452     }
453     halConfig->num_phrases = i;
454 
455     halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
456     halConfig->data_size = config->data.size();
457     uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
458     const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
459     memcpy(dst, src, config->data.size());
460     return halConfig;
461 }
462 
convertRecognitionConfigToHalHeader(const V2_3::RecognitionConfig * config)463 struct sound_trigger_recognition_config_header* SoundTriggerHw::convertRecognitionConfigToHalHeader(
464         const V2_3::RecognitionConfig* config) {
465     sp<IMemory> memory;
466     const V2_1::ISoundTriggerHw::RecognitionConfig* config_2_1 = &config->base;
467     const V2_0::ISoundTriggerHw::RecognitionConfig* config_2_0 = &config_2_1->header;
468 
469     size_t allocSize =
470             sizeof(struct sound_trigger_recognition_config_extended_1_3) + config_2_1->data.size();
471     struct sound_trigger_recognition_config_extended_1_3* halConfigExtended =
472             static_cast<struct sound_trigger_recognition_config_extended_1_3*>(malloc(allocSize));
473     LOG_ALWAYS_FATAL_IF(halConfigExtended == nullptr,
474                         "malloc failed for size %zu in convertRecognitionConfigToHalHeader",
475                         allocSize);
476     halConfigExtended->header.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_3;
477     halConfigExtended->header.size = allocSize;
478 
479     struct sound_trigger_recognition_config* halConfigBase = &halConfigExtended->base;
480 
481     halConfigBase->capture_handle = (audio_io_handle_t)config_2_0->captureHandle;
482     halConfigBase->capture_device = (audio_devices_t)config_2_0->captureDevice;
483     halConfigBase->capture_requested = config_2_0->captureRequested;
484 
485     unsigned int i;
486     for (i = 0; i < config_2_0->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
487         convertPhraseRecognitionExtraToHal(&halConfigBase->phrases[i], &config_2_0->phrases[i]);
488     }
489     halConfigBase->num_phrases = i;
490 
491     halConfigBase->data_offset = sizeof(struct sound_trigger_recognition_config_extended_1_3);
492     halConfigBase->data_size = config_2_1->data.size();
493     if (config_2_1->data.size() != 0) {
494         memory = mapMemory(config_2_1->data);
495         LOG_ALWAYS_FATAL_IF(memory == nullptr,
496                             "failed to map config memory in convertRecognitionConfigToHalHeader");
497         memory->read();
498 
499         uint8_t* dst = reinterpret_cast<uint8_t*>(halConfigExtended) + halConfigBase->data_offset;
500         const uint8_t* src = static_cast<const uint8_t*>(static_cast<void*>(memory->getPointer()));
501         memcpy(dst, src, config_2_1->data.size());
502 
503         memory->commit();
504     }
505 
506     halConfigExtended->audio_capabilities = config->audioCapabilities;
507 
508     return &halConfigExtended->header;
509 }
510 
511 // static
convertSoundModelEventFromHal(V2_0::ISoundTriggerHwCallback::ModelEvent * event,const struct sound_trigger_model_event * halEvent)512 void SoundTriggerHw::convertSoundModelEventFromHal(
513         V2_0::ISoundTriggerHwCallback::ModelEvent* event,
514         const struct sound_trigger_model_event* halEvent) {
515     event->status = (V2_0::ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
516     // event->model to be remapped by called
517     event->data.setToExternal(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) +
518                                       halEvent->data_offset,
519                               halEvent->data_size);
520 }
521 
522 // static
convertPhaseRecognitionEventFromHal(V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent * event,const struct sound_trigger_phrase_recognition_event * halEvent)523 void SoundTriggerHw::convertPhaseRecognitionEventFromHal(
524         V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
525         const struct sound_trigger_phrase_recognition_event* halEvent) {
526     event->phraseExtras.resize(halEvent->num_phrases);
527     for (unsigned int i = 0; i < halEvent->num_phrases; i++) {
528         convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]);
529     }
530     convertRecognitionEventFromHal(&event->common, &halEvent->common);
531 }
532 
533 // static
convertRecognitionEventFromHal(V2_0::ISoundTriggerHwCallback::RecognitionEvent * event,const struct sound_trigger_recognition_event * halEvent)534 void SoundTriggerHw::convertRecognitionEventFromHal(
535         V2_0::ISoundTriggerHwCallback::RecognitionEvent* event,
536         const struct sound_trigger_recognition_event* halEvent) {
537     event->status = static_cast<V2_0::ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
538     event->type = static_cast<V2_0::SoundModelType>(halEvent->type);
539     // event->model to be remapped by called
540     event->captureAvailable = halEvent->capture_available;
541     event->captureSession = halEvent->capture_session;
542     event->captureDelayMs = halEvent->capture_delay_ms;
543     event->capturePreambleMs = halEvent->capture_preamble_ms;
544     event->triggerInData = halEvent->trigger_in_data;
545     event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
546     event->audioConfig.channelMask =
547             (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
548     event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
549     event->data.setToExternal(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) +
550                                       halEvent->data_offset,
551                               halEvent->data_size);
552 }
553 
554 // static
convertPhraseRecognitionExtraFromHal(V2_0::PhraseRecognitionExtra * extra,const struct sound_trigger_phrase_recognition_extra * halExtra)555 void SoundTriggerHw::convertPhraseRecognitionExtraFromHal(
556         V2_0::PhraseRecognitionExtra* extra,
557         const struct sound_trigger_phrase_recognition_extra* halExtra) {
558     extra->id = halExtra->id;
559     extra->recognitionModes = halExtra->recognition_modes;
560     extra->confidenceLevel = halExtra->confidence_level;
561 
562     extra->levels.resize(halExtra->num_levels);
563     for (unsigned int i = 0; i < halExtra->num_levels; i++) {
564         extra->levels[i].userId = halExtra->levels[i].user_id;
565         extra->levels[i].levelPercent = halExtra->levels[i].level;
566     }
567 }
568 
recognitionCallback(struct sound_trigger_recognition_event * halEvent)569 void SoundTriggerHw::SoundModelClient_2_0::recognitionCallback(
570         struct sound_trigger_recognition_event* halEvent) {
571     if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
572         V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
573         convertPhaseRecognitionEventFromHal(
574                 &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
575         event.common.model = mId;
576         mCallback->phraseRecognitionCallback(event, mCookie);
577     } else {
578         V2_0::ISoundTriggerHwCallback::RecognitionEvent event;
579         convertRecognitionEventFromHal(&event, halEvent);
580         event.model = mId;
581         mCallback->recognitionCallback(event, mCookie);
582     }
583 }
584 
soundModelCallback(struct sound_trigger_model_event * halEvent)585 void SoundTriggerHw::SoundModelClient_2_0::soundModelCallback(
586         struct sound_trigger_model_event* halEvent) {
587     V2_0::ISoundTriggerHwCallback::ModelEvent event;
588     convertSoundModelEventFromHal(&event, halEvent);
589     event.model = mId;
590     mCallback->soundModelCallback(event, mCookie);
591 }
592 
593 // Begin V2_1 implementation, copied from
594 // hardware/interfaces/soundtrigger/2.1/default/SoundTriggerHw.cpp
595 
596 namespace {
597 
598 // Backs up by the vector with the contents of shared memory.
599 // It is assumed that the passed hidl_vector is empty, so it's
600 // not cleared if the memory is a null object.
601 // The caller needs to keep the returned sp<IMemory> as long as
602 // the data is needed.
memoryAsVector(const hidl_memory & m,hidl_vec<uint8_t> * vec)603 std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
604     sp<IMemory> memory;
605     if (m.size() == 0) {
606         return std::make_pair(true, memory);
607     }
608     memory = mapMemory(m);
609     if (memory != nullptr) {
610         memory->read();
611         vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
612                            memory->getSize());
613         return std::make_pair(true, memory);
614     }
615     ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
616     return std::make_pair(false, memory);
617 }
618 
619 // Moves the data from the vector into allocated shared memory,
620 // emptying the vector.
621 // It is assumed that the passed hidl_memory is a null object, so it's
622 // not reset if the vector is empty.
623 // The caller needs to keep the returned sp<IMemory> as long as
624 // the data is needed.
moveVectorToMemory(hidl_vec<uint8_t> * v,hidl_memory * mem)625 std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
626     sp<IMemory> memory;
627     if (v->size() == 0) {
628         return std::make_pair(true, memory);
629     }
630     sp<IAllocator> ashmem = IAllocator::getService("ashmem");
631     if (ashmem == 0) {
632         ALOGE("Failed to retrieve ashmem allocator service");
633         return std::make_pair(false, memory);
634     }
635     bool success = false;
636     Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
637         success = s;
638         if (success) *mem = m;
639     });
640     if (r.isOk() && success) {
641         memory = hardware::mapMemory(*mem);
642         if (memory != 0) {
643             memory->update();
644             memcpy(memory->getPointer(), v->data(), v->size());
645             memory->commit();
646             v->resize(0);
647             return std::make_pair(true, memory);
648         } else {
649             ALOGE("Failed to map allocated ashmem");
650         }
651     } else {
652         ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
653     }
654     return std::make_pair(false, memory);
655 }
656 
657 }  // namespace
658 
loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel & soundModel,const sp<V2_1::ISoundTriggerHwCallback> & callback,int32_t cookie,V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb)659 Return<void> SoundTriggerHw::loadSoundModel_2_1(
660         const V2_1::ISoundTriggerHw::SoundModel& soundModel,
661         const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
662         V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb) {
663     // It is assumed that legacy data vector is empty, thus making copy is cheap.
664     V2_0::ISoundTriggerHw::SoundModel soundModel_2_0(soundModel.header);
665     auto result = memoryAsVector(soundModel.data, &soundModel_2_0.data);
666     if (result.first) {
667         sp<SoundModelClient> client =
668                 new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
669         _hidl_cb(doLoadSoundModel(soundModel_2_0, client), client->getId());
670         return Void();
671     }
672     _hidl_cb(-ENOMEM, 0);
673     return Void();
674 }
675 
loadPhraseSoundModel_2_1(const V2_1::ISoundTriggerHw::PhraseSoundModel & soundModel,const sp<V2_1::ISoundTriggerHwCallback> & callback,int32_t cookie,V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb)676 Return<void> SoundTriggerHw::loadPhraseSoundModel_2_1(
677         const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
678         const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
679         V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb) {
680     V2_0::ISoundTriggerHw::PhraseSoundModel soundModel_2_0;
681     // It is assumed that legacy data vector is empty, thus making copy is cheap.
682     soundModel_2_0.common = soundModel.common.header;
683     // Avoid copying phrases data.
684     soundModel_2_0.phrases.setToExternal(
685             const_cast<V2_0::ISoundTriggerHw::Phrase*>(soundModel.phrases.data()),
686             soundModel.phrases.size());
687     auto result = memoryAsVector(soundModel.common.data, &soundModel_2_0.common.data);
688     if (result.first) {
689         sp<SoundModelClient> client =
690                 new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
691         _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel_2_0, client),
692                  client->getId());
693         return Void();
694     }
695     _hidl_cb(-ENOMEM, 0);
696     return Void();
697 }
698 
startRecognition_2_1(int32_t modelHandle,const V2_1::ISoundTriggerHw::RecognitionConfig & config,const sp<V2_1::ISoundTriggerHwCallback> & callback,int32_t cookie)699 Return<int32_t> SoundTriggerHw::startRecognition_2_1(
700         int32_t modelHandle, const V2_1::ISoundTriggerHw::RecognitionConfig& config,
701         const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie) {
702     // It is assumed that legacy data vector is empty, thus making copy is cheap.
703     V2_0::ISoundTriggerHw::RecognitionConfig config_2_0(config.header);
704     auto result = memoryAsVector(config.data, &config_2_0.data);
705     return result.first ? startRecognition(modelHandle, config_2_0, callback, cookie)
706                         : Return<int32_t>(-ENOMEM);
707 }
708 
recognitionCallback(struct sound_trigger_recognition_event * halEvent)709 void SoundTriggerHw::SoundModelClient_2_1::recognitionCallback(
710         struct sound_trigger_recognition_event* halEvent) {
711     if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
712         V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
713         convertPhaseRecognitionEventFromHal(
714                 &event_2_0, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
715         event_2_0.common.model = mId;
716         V2_1::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
717         event.phraseExtras.setToExternal(event_2_0.phraseExtras.data(),
718                                          event_2_0.phraseExtras.size());
719         auto result = moveVectorToMemory(&event_2_0.common.data, &event.common.data);
720         if (result.first) {
721             // The data vector is now empty, thus copying is cheap.
722             event.common.header = event_2_0.common;
723             mCallback->phraseRecognitionCallback_2_1(event, mCookie);
724         }
725     } else {
726         V2_1::ISoundTriggerHwCallback::RecognitionEvent event;
727         convertRecognitionEventFromHal(&event.header, halEvent);
728         event.header.model = mId;
729         auto result = moveVectorToMemory(&event.header.data, &event.data);
730         if (result.first) {
731             mCallback->recognitionCallback_2_1(event, mCookie);
732         }
733     }
734 }
735 
soundModelCallback(struct sound_trigger_model_event * halEvent)736 void SoundTriggerHw::SoundModelClient_2_1::soundModelCallback(
737         struct sound_trigger_model_event* halEvent) {
738     V2_1::ISoundTriggerHwCallback::ModelEvent event;
739     convertSoundModelEventFromHal(&event.header, halEvent);
740     event.header.model = mId;
741     auto result = moveVectorToMemory(&event.header.data, &event.data);
742     if (result.first) {
743         mCallback->soundModelCallback_2_1(event, mCookie);
744     }
745 }
746 
747 // Begin V2_2 implementation, copied from
748 // hardware/interfaces/soundtrigger/2.2/default/SoundTriggerHw.cpp
749 
getModelState(int32_t modelHandle)750 Return<int32_t> SoundTriggerHw::getModelState(int32_t modelHandle) {
751     sp<SoundModelClient> client;
752     if (mHwDevice == NULL) {
753         return -ENODEV;
754     }
755 
756     {
757         AutoMutex lock(mLock);
758         client = mClients.valueFor(modelHandle);
759         if (client == 0) {
760             return -ENOSYS;
761         }
762     }
763 
764     return mHwDevice->get_model_state(mHwDevice, client->getHalHandle());
765 }
766 
767 // Begin V2_3 implementation
768 
getProperties_2_3(ISoundTriggerHw::getProperties_2_3_cb _hidl_cb)769 Return<void> SoundTriggerHw::getProperties_2_3(ISoundTriggerHw::getProperties_2_3_cb _hidl_cb) {
770     ALOGV("getProperties_2_3() mHwDevice %p", mHwDevice);
771     int ret = 0;
772     V2_3::Properties properties;
773     const struct sound_trigger_properties_header* header;
774 
775     if (mHwDevice == NULL) {
776         ret = -ENODEV;
777         goto exit;
778     }
779 
780     header = mHwDevice->get_properties_extended(mHwDevice);
781 
782     convertPropertiesFromHal(&properties, header);
783 
784     ALOGV("getProperties_2_3 implementor %s supportedModelArch %s",
785           properties.base.implementor.c_str(), properties.supportedModelArch.c_str());
786 
787 exit:
788     _hidl_cb(ret, properties);
789     return Void();
790 }
791 
startRecognition_2_3(int32_t modelHandle,const V2_3::RecognitionConfig & config)792 Return<int32_t> SoundTriggerHw::startRecognition_2_3(int32_t modelHandle,
793                                                      const V2_3::RecognitionConfig& config) {
794     int32_t ret;
795     sp<SoundTriggerHw::SoundModelClient> client;
796     struct sound_trigger_recognition_config_header* header;
797 
798     if (mHwDevice == NULL) {
799         ret = -ENODEV;
800         goto exit;
801     }
802 
803     {
804         AutoMutex lock(mLock);
805         client = mClients.valueFor(modelHandle);
806         if (client == 0) {
807             ret = -ENOSYS;
808             goto exit;
809         }
810     }
811 
812     header = convertRecognitionConfigToHalHeader(&config);
813 
814     if (header == nullptr) {
815         ret = -EINVAL;
816         goto exit;
817     }
818     ret = mHwDevice->start_recognition_extended(mHwDevice, client->getHalHandle(), header,
819                                                 recognitionCallback_, client.get());
820 
821     free(header);
822 
823 exit:
824     return ret;
825 }
826 
setParameter(V2_0::SoundModelHandle modelHandle,ModelParameter modelParam,int32_t value)827 Return<int32_t> SoundTriggerHw::setParameter(V2_0::SoundModelHandle modelHandle,
828                                              ModelParameter modelParam, int32_t value) {
829     sp<SoundModelClient> client;
830     if (mHwDevice == NULL) {
831         return -ENODEV;
832     }
833 
834     {
835         AutoMutex lock(mLock);
836         client = mClients.valueFor(modelHandle);
837         if (client == 0) {
838             return -EINVAL;
839         }
840     }
841 
842     return mHwDevice->set_parameter(mHwDevice, client->getHalHandle(),
843                                     convertModelParameterToHal(modelParam), value);
844 }
845 
getParameter(V2_0::SoundModelHandle modelHandle,ModelParameter modelParam,getParameter_cb _hidl_cb)846 Return<void> SoundTriggerHw::getParameter(V2_0::SoundModelHandle modelHandle,
847                                           ModelParameter modelParam, getParameter_cb _hidl_cb) {
848     sp<SoundModelClient> client;
849     if (mHwDevice == NULL) {
850         _hidl_cb(-ENODEV, 0);
851         return Void();
852     }
853 
854     {
855         AutoMutex lock(mLock);
856         client = mClients.valueFor(modelHandle);
857         if (client == 0) {
858             _hidl_cb(-EINVAL, 0);
859             return Void();
860         }
861     }
862 
863     int32_t value;
864     int32_t status = mHwDevice->get_parameter(mHwDevice, client->getHalHandle(),
865                                               convertModelParameterToHal(modelParam), &value);
866     _hidl_cb(status, value);
867     return Void();
868 }
869 
queryParameter(V2_0::SoundModelHandle modelHandle,ModelParameter modelParam,queryParameter_cb _hidl_cb)870 Return<void> SoundTriggerHw::queryParameter(V2_0::SoundModelHandle modelHandle,
871                                             ModelParameter modelParam, queryParameter_cb _hidl_cb) {
872     OptionalModelParameterRange optionalParamRange;
873     sp<SoundModelClient> client;
874     if (mHwDevice == NULL) {
875         _hidl_cb(-ENODEV, optionalParamRange);
876         return Void();
877     }
878 
879     {
880         AutoMutex lock(mLock);
881         client = mClients.valueFor(modelHandle);
882         if (client == 0) {
883             _hidl_cb(-EINVAL, optionalParamRange);
884             return Void();
885         }
886     }
887 
888     sound_trigger_model_parameter_range_t paramRange;
889     int32_t status = mHwDevice->query_parameter(
890             mHwDevice, client->getHalHandle(), convertModelParameterToHal(modelParam), &paramRange);
891 
892     if (status == 0 && paramRange.is_supported) {
893         optionalParamRange.range({.start = paramRange.start, .end = paramRange.end});
894     }
895     _hidl_cb(status, optionalParamRange);
896     return Void();
897 }
898 
899 // static
convertModelParameterToHal(ModelParameter param)900 sound_trigger_model_parameter_t SoundTriggerHw::convertModelParameterToHal(ModelParameter param) {
901     switch (param) {
902         case ModelParameter::THRESHOLD_FACTOR:
903             return MODEL_PARAMETER_THRESHOLD_FACTOR;
904         case ModelParameter::INVALID:
905         default:
906             return MODEL_PARAMETER_INVALID;
907     }
908 }
909 
910 // Methods from ::android::hidl::base::V1_0::IBase follow.
911 
HIDL_FETCH_ISoundTriggerHw(const char *)912 ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) {
913     return new SoundTriggerHw();
914 }
915 
916 }  // namespace implementation
917 }  // namespace V2_3
918 }  // namespace soundtrigger
919 }  // namespace hardware
920 }  // namespace android
921