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