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