127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent/* 227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * Copyright (C) 2016 The Android Open Source Project 327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * 427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License"); 527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * you may not use this file except in compliance with the License. 627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * You may obtain a copy of the License at 727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * 827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * http://www.apache.org/licenses/LICENSE-2.0 927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * 1027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * Unless required by applicable law or agreed to in writing, software 1127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS, 1227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * See the License for the specific language governing permissions and 1427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent * limitations under the License. 1527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent */ 1627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 1727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent#define LOG_TAG "SoundTriggerHalImpl" 1827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent//#define LOG_NDEBUG 0 1927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 20f9d303435d80161fabb16cdff3b8f2f75f362480Yifan Hong#include <android/log.h> 2127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent#include "SoundTriggerHalImpl.h" 2227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 2327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 2427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentnamespace android { 2527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentnamespace hardware { 2627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentnamespace soundtrigger { 2727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentnamespace V2_0 { 2827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentnamespace implementation { 2927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 3027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent// static 3127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event *halEvent, 3227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent void *cookie) 3327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 3427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (halEvent == NULL) { 3527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGW("soundModelCallback called with NULL event"); 3627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return; 3727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 3827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sp<SoundModelClient> client = 3927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent wp<SoundModelClient>(static_cast<SoundModelClient *>(cookie)).promote(); 4027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (client == 0) { 4127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGW("soundModelCallback called on stale client"); 4227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return; 4327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 4427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (halEvent->model != client->mHalHandle) { 4527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGW("soundModelCallback call with wrong handle %d on client with handle %d", 4627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent (int)halEvent->model, (int)client->mHalHandle); 4727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return; 4827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 4927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 5027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHwCallback::ModelEvent event; 5127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent convertSoundModelEventFromHal(&event, halEvent); 5227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event.model = client->mId; 5327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 5427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client->mCallback->soundModelCallback(event, client->mCookie); 5527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 5627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 5727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent// static 5827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::recognitionCallback(struct sound_trigger_recognition_event *halEvent, 5927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent void *cookie) 6027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 6127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (halEvent == NULL) { 6227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGW("recognitionCallback call NULL event"); 6327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return; 6427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 6527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sp<SoundModelClient> client = 6627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent wp<SoundModelClient>(static_cast<SoundModelClient *>(cookie)).promote(); 6727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (client == 0) { 6827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGW("soundModelCallback called on stale client"); 6927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return; 7027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 7127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 7227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHwCallback::RecognitionEvent *event = convertRecognitionEventFromHal(halEvent); 7327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->model = client->mId; 7427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) { 7527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client->mCallback->phraseRecognitionCallback( 7627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent *(reinterpret_cast<ISoundTriggerHwCallback::PhraseRecognitionEvent *>(event)), 7727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client->mCookie); 7827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } else { 7927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client->mCallback->recognitionCallback(*event, client->mCookie); 8027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 8127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent delete event; 8227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 8327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 8427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 8527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 8627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent// Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow. 8727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentReturn<void> SoundTriggerHalImpl::getProperties(getProperties_cb _hidl_cb) 8827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 8927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGV("getProperties() mHwDevice %p", mHwDevice); 9027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int ret; 9127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent struct sound_trigger_properties halProperties; 9227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHw::Properties properties; 9327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 9427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice == NULL) { 9527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENODEV; 9627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 9727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 9827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 9927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = mHwDevice->get_properties(mHwDevice, &halProperties); 10027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 10127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent convertPropertiesFromHal(&properties, &halProperties); 10227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 10327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGV("getProperties implementor %s recognitionModes %08x", 10427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties.implementor.c_str(), properties.recognitionModes); 10527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 10627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentexit: 10727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent _hidl_cb(ret, properties); 10827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return Void(); 10927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 11027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 11127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentint SoundTriggerHalImpl::doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel, 11227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const sp<ISoundTriggerHwCallback>& callback, 11327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHwCallback::CallbackCookie cookie, 11427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uint32_t *modelId) 11527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 11627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int32_t ret = 0; 11727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent struct sound_trigger_sound_model *halSoundModel; 11827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent *modelId = 0; 11927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sp<SoundModelClient> client; 12027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 12127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size()); 12227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 12327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice == NULL) { 12427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENODEV; 12527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 12627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 12727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 12827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halSoundModel = convertSoundModelToHal(&soundModel); 12927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (halSoundModel == NULL) { 13027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -EINVAL; 13127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 13227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 13327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 13427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent { 13527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent AutoMutex lock(mLock); 13627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent do { 13727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent *modelId = nextUniqueId(); 13827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } while (mClients.valueFor(*modelId) != 0 && *modelId != 0); 13927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 14027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent LOG_ALWAYS_FATAL_IF(*modelId == 0, 14106e939be44d093ce756c624e7be7341c12ae0282Bryan Eyler "wrap around in sound model IDs, num loaded models %zu", mClients.size()); 14227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 14327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client = new SoundModelClient(*modelId, callback, cookie); 14427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 14527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback, 14627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client.get(), &client->mHalHandle); 14727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 14827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent free(halSoundModel); 14927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 15027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (ret != 0) { 15127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 15227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 15327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 15427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent { 15527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent AutoMutex lock(mLock); 15627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent mClients.add(*modelId, client); 15727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 15827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 15927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentexit: 16027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return ret; 16127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 16227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 16327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentReturn<void> SoundTriggerHalImpl::loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel, 16427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const sp<ISoundTriggerHwCallback>& callback, 16527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHwCallback::CallbackCookie cookie, 16627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent loadSoundModel_cb _hidl_cb) 16727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 16827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uint32_t modelId = 0; 16927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int32_t ret = doLoadSoundModel(soundModel, callback, cookie, &modelId); 17027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 17127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent _hidl_cb(ret, modelId); 17227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return Void(); 17327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 17427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 17527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentReturn<void> SoundTriggerHalImpl::loadPhraseSoundModel( 17627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const ISoundTriggerHw::PhraseSoundModel& soundModel, 17727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const sp<ISoundTriggerHwCallback>& callback, 17827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHwCallback::CallbackCookie cookie, 17927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) 18027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 18127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uint32_t modelId = 0; 18227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int32_t ret = doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel, 18327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent callback, cookie, &modelId); 18427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 18527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent _hidl_cb(ret, modelId); 18627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return Void(); 18727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 18827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 18927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentReturn<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle) 19027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 19127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int32_t ret; 19227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sp<SoundModelClient> client; 19327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 19427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice == NULL) { 19527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENODEV; 19627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 19727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 19827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 19927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent { 20027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent AutoMutex lock(mLock); 20127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client = mClients.valueFor(modelHandle); 20227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (client == 0) { 20327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENOSYS; 20427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 20527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 20627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 20727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 20827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = mHwDevice->unload_sound_model(mHwDevice, client->mHalHandle); 20927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 21027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent mClients.removeItem(modelHandle); 21127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 21227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentexit: 21327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return ret; 21427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 21527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 21627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentReturn<int32_t> SoundTriggerHalImpl::startRecognition(SoundModelHandle modelHandle, 21727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const ISoundTriggerHw::RecognitionConfig& config, 21827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const sp<ISoundTriggerHwCallback>& callback __unused, 21927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHwCallback::CallbackCookie cookie __unused) 22027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 22127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int32_t ret; 22227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sp<SoundModelClient> client; 22327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent struct sound_trigger_recognition_config *halConfig; 22427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 22527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice == NULL) { 22627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENODEV; 22727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 22827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 22927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 23027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent { 23127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent AutoMutex lock(mLock); 23227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client = mClients.valueFor(modelHandle); 23327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (client == 0) { 23427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENOSYS; 23527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 23627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 23727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 23827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 23927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 24027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halConfig = convertRecognitionConfigToHal(&config); 24127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 24227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (halConfig == NULL) { 24327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -EINVAL; 24427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 24527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 24627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = mHwDevice->start_recognition(mHwDevice, client->mHalHandle, halConfig, 24727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent recognitionCallback, client.get()); 24827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 24927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent free(halConfig); 25027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 25127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentexit: 25227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return ret; 25327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 25427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 25527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentReturn<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle) 25627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 25727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int32_t ret; 25827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sp<SoundModelClient> client; 25927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice == NULL) { 26027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENODEV; 26127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 26227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 26327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 26427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent { 26527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent AutoMutex lock(mLock); 26627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent client = mClients.valueFor(modelHandle); 26727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (client == 0) { 26827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENOSYS; 26927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 27027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 27127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 27227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 27327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = mHwDevice->stop_recognition(mHwDevice, client->mHalHandle); 27427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 27527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentexit: 27627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return ret; 27727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 27827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 27927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentReturn<int32_t> SoundTriggerHalImpl::stopAllRecognitions() 28027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 28127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int32_t ret; 28227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice == NULL) { 28327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENODEV; 28427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent goto exit; 28527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 28627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 28727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 && 28827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent mHwDevice->stop_all_recognitions) { 28927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = mHwDevice->stop_all_recognitions(mHwDevice); 29027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } else { 29127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ret = -ENOSYS; 29227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 29327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentexit: 29427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return ret; 29527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 29627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 2973acaa668c102cf096a9e3bc540d7a74ca3ac5c36Mikhail NaganovSoundTriggerHalImpl::SoundTriggerHalImpl() 2983acaa668c102cf096a9e3bc540d7a74ca3ac5c36Mikhail Naganov : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) 29927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 30027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 30127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 30227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::onFirstRef() 30327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 30427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const hw_module_t *mod; 30527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent int rc; 30627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 30727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod); 30827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (rc != 0) { 30927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGE("couldn't load sound trigger module %s.%s (%s)", 31027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc)); 31127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return; 31227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 31327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent rc = sound_trigger_hw_device_open(mod, &mHwDevice); 31427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (rc != 0) { 31527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGE("couldn't open sound trigger hw device in %s.%s (%s)", 31627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc)); 31727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent mHwDevice = NULL; 31827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return; 31927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 32027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 || 32127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) { 32227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version); 32327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sound_trigger_hw_device_close(mHwDevice); 32427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent mHwDevice = NULL; 32527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return; 32627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 32727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 32827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice); 32927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 33027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 33127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentSoundTriggerHalImpl::~SoundTriggerHalImpl() 33227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 33327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (mHwDevice != NULL) { 33427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sound_trigger_hw_device_close(mHwDevice); 33527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 33627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 33727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 33827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentuint32_t SoundTriggerHalImpl::nextUniqueId() 33927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 34027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return (uint32_t) atomic_fetch_add_explicit(&mNextModelId, 34127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent (uint_fast32_t) 1, memory_order_acq_rel); 34227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 34327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 34427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::convertUuidFromHal(Uuid *uuid, 34527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const sound_trigger_uuid_t *halUuid) 34627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 34727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uuid->timeLow = halUuid->timeLow; 34827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uuid->timeMid = halUuid->timeMid; 34927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uuid->versionAndTimeHigh = halUuid->timeHiAndVersion; 35027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uuid->variantAndClockSeqHigh = halUuid->clockSeq; 35127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent memcpy(&uuid->node[0], &halUuid->node[0], 6); 35227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 35327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 35427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t *halUuid, 35527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const Uuid *uuid) 35627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 35727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halUuid->timeLow = uuid->timeLow; 35827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halUuid->timeMid = uuid->timeMid; 35927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halUuid->timeHiAndVersion = uuid->versionAndTimeHigh; 36027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halUuid->clockSeq = uuid->variantAndClockSeqHigh; 36127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent memcpy(&halUuid->node[0], &uuid->node[0], 6); 36227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 36327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 36427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::convertPropertiesFromHal( 36527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHw::Properties *properties, 36627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const struct sound_trigger_properties *halProperties) 36727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 36827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->implementor = halProperties->implementor; 36927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->description = halProperties->description; 37027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->version = halProperties->version; 37127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent convertUuidFromHal(&properties->uuid, &halProperties->uuid); 37227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->maxSoundModels = halProperties->max_sound_models; 37327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->maxKeyPhrases = halProperties->max_key_phrases; 37427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->maxUsers = halProperties->max_users; 37527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->recognitionModes = halProperties->recognition_modes; 37627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->captureTransition = halProperties->capture_transition; 37727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->maxBufferMs = halProperties->max_buffer_ms; 37827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->concurrentCapture = halProperties->concurrent_capture; 37927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->triggerInEvent = halProperties->trigger_in_event; 38027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent properties->powerConsumptionMw = halProperties->power_consumption_mw; 38127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 38227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 38327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 38427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::convertTriggerPhraseToHal( 38527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent struct sound_trigger_phrase *halTriggerPhrase, 38627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const ISoundTriggerHw::Phrase *triggerPhrase) 38727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 38827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halTriggerPhrase->id = triggerPhrase->id; 38927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes; 39027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent unsigned int i; 39127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent for (i = 0; i < triggerPhrase->users.size(); i++) { 39227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halTriggerPhrase->users[i] = triggerPhrase->users[i]; 39327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 39427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halTriggerPhrase->num_users = i; 39527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 39627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent strlcpy(halTriggerPhrase->locale, 39727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN); 39827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent strlcpy(halTriggerPhrase->text, 39927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN); 40027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 40127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 40227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentstruct sound_trigger_sound_model *SoundTriggerHalImpl::convertSoundModelToHal( 40327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const ISoundTriggerHw::SoundModel *soundModel) 40427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 40527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent struct sound_trigger_sound_model *halModel = NULL; 40627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (soundModel->type == SoundModelType::KEYPHRASE) { 40727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent size_t allocSize = 40827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size(); 40927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent struct sound_trigger_phrase_sound_model *halKeyPhraseModel = 41027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent static_cast<struct sound_trigger_phrase_sound_model *>(malloc(allocSize)); 41127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL, 41227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent "malloc failed for size %zu in convertSoundModelToHal PHRASE", allocSize); 41327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 41427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const ISoundTriggerHw::PhraseSoundModel *keyPhraseModel = 41527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel *>(soundModel); 41627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 41727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent size_t i; 41827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) { 41927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], 42027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent &keyPhraseModel->phrases[i]); 42127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 42227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halKeyPhraseModel->num_phrases = (unsigned int)i; 42327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halModel = reinterpret_cast<struct sound_trigger_sound_model *>(halKeyPhraseModel); 42427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model); 42527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } else { 42627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent size_t allocSize = 42727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent sizeof(struct sound_trigger_sound_model) + soundModel->data.size(); 42827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halModel = static_cast<struct sound_trigger_sound_model *>(malloc(allocSize)); 42927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent LOG_ALWAYS_FATAL_IF(halModel == NULL, 43027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent "malloc failed for size %zu in convertSoundModelToHal GENERIC", 43127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent allocSize); 43227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 43327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halModel->data_offset = sizeof(struct sound_trigger_sound_model); 43427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 43527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halModel->type = (sound_trigger_sound_model_type_t)soundModel->type; 43627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent convertUuidToHal(&halModel->uuid, &soundModel->uuid); 43727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid); 43827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halModel->data_size = soundModel->data.size(); 43927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uint8_t *dst = reinterpret_cast<uint8_t *>(halModel) + halModel->data_offset; 44027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const uint8_t *src = reinterpret_cast<const uint8_t *>(&soundModel->data[0]); 44127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent memcpy(dst, src, soundModel->data.size()); 44227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 44327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return halModel; 44427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 44527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 44627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::convertPhraseRecognitionExtraToHal( 44727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent struct sound_trigger_phrase_recognition_extra *halExtra, 44827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const PhraseRecognitionExtra *extra) 44927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 45027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halExtra->id = extra->id; 45127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halExtra->recognition_modes = extra->recognitionModes; 45227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halExtra->confidence_level = extra->confidenceLevel; 45327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 45427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent unsigned int i; 45527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) { 45627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halExtra->levels[i].user_id = extra->levels[i].userId; 45727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halExtra->levels[i].level = extra->levels[i].levelPercent; 45827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 45927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halExtra->num_levels = i; 46027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 46127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 46227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentstruct sound_trigger_recognition_config *SoundTriggerHalImpl::convertRecognitionConfigToHal( 46327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const ISoundTriggerHw::RecognitionConfig *config) 46427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 46527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size(); 46627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent struct sound_trigger_recognition_config *halConfig = 46727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent static_cast<struct sound_trigger_recognition_config *>(malloc(allocSize)); 46827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 46927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent LOG_ALWAYS_FATAL_IF(halConfig == NULL, 47027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent "malloc failed for size %zu in convertRecognitionConfigToHal", 47127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent allocSize); 47227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 47327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halConfig->capture_handle = (audio_io_handle_t)config->captureHandle; 47427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halConfig->capture_device = (audio_devices_t)config->captureDevice; 47527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halConfig->capture_requested = config->captureRequested; 47627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 47727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent unsigned int i; 47827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) { 47927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], 48027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent &config->phrases[i]); 48127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 48227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halConfig->num_phrases = i; 48327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 48427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halConfig->data_offset = sizeof(struct sound_trigger_recognition_config); 48527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halConfig->data_size = config->data.size(); 48627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent uint8_t *dst = reinterpret_cast<uint8_t *>(halConfig) + halConfig->data_offset; 48727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const uint8_t *src = reinterpret_cast<const uint8_t *>(&config->data[0]); 48827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent memcpy(dst, src, config->data.size()); 48927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return halConfig; 49027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 49127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 49227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent// static 49327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent *event, 49427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const struct sound_trigger_model_event *halEvent) 49527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 49627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->status = (ISoundTriggerHwCallback::SoundModelStatus)halEvent->status; 49727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent // event->model to be remapped by called 49827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->data.setToExternal( 49927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(halEvent)) + halEvent->data_offset, 50027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halEvent->data_size); 50127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 50227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 50327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent// static 50427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric LaurentISoundTriggerHwCallback::RecognitionEvent *SoundTriggerHalImpl::convertRecognitionEventFromHal( 50527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const struct sound_trigger_recognition_event *halEvent) 50627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 50727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHwCallback::RecognitionEvent * event; 50827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 50927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) { 51027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const struct sound_trigger_phrase_recognition_event *halPhraseEvent = 51127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent reinterpret_cast<const struct sound_trigger_phrase_recognition_event *>(halEvent); 51227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ISoundTriggerHwCallback::PhraseRecognitionEvent *phraseEvent = 51327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent new ISoundTriggerHwCallback::PhraseRecognitionEvent(); 51427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 51527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent PhraseRecognitionExtra *phraseExtras = 51627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent new PhraseRecognitionExtra[halPhraseEvent->num_phrases]; 51727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent for (unsigned int i = 0; i < halPhraseEvent->num_phrases; i++) { 51827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent convertPhraseRecognitionExtraFromHal(&phraseExtras[i], 51927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent &halPhraseEvent->phrase_extras[i]); 52027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 52127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent phraseEvent->phraseExtras.setToExternal(phraseExtras, halPhraseEvent->num_phrases); 52227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent // FIXME: transfer buffer ownership. should have a method for that in hidl_vec 52327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent phraseEvent->phraseExtras.resize(halPhraseEvent->num_phrases); 52427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent delete[] phraseExtras; 52527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event = reinterpret_cast<ISoundTriggerHwCallback::RecognitionEvent *>(phraseEvent); 52627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } else { 52727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event = new ISoundTriggerHwCallback::RecognitionEvent(); 52827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 52927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 53027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->status = static_cast<ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status); 53127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->type = static_cast<SoundModelType>(halEvent->type); 53227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent // event->model to be remapped by called 53327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->captureAvailable = halEvent->capture_available; 53427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->captureSession = halEvent->capture_session; 53527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->captureDelayMs = halEvent->capture_delay_ms; 53627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->capturePreambleMs = halEvent->capture_preamble_ms; 53727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->triggerInData = halEvent->trigger_in_data; 53827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate; 53927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->audioConfig.channelMask = 54027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask; 54127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format; 54227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent event->data.setToExternal( 54327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(halEvent)) + halEvent->data_offset, 54427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent halEvent->data_size); 54527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 54627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent return event; 54727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 54827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 54927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent// static 55027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurentvoid SoundTriggerHalImpl::convertPhraseRecognitionExtraFromHal( 55127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent PhraseRecognitionExtra *extra, 55227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent const struct sound_trigger_phrase_recognition_extra *halExtra) 55327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 55427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent extra->id = halExtra->id; 55527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent extra->recognitionModes = halExtra->recognition_modes; 55627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent extra->confidenceLevel = halExtra->confidence_level; 55727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 55827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent ConfidenceLevel *levels = 55927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent new ConfidenceLevel[halExtra->num_levels]; 56027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent for (unsigned int i = 0; i < halExtra->num_levels; i++) { 56127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent levels[i].userId = halExtra->levels[i].user_id; 56227ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent levels[i].levelPercent = halExtra->levels[i].level; 56327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent } 56427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent extra->levels.setToExternal(levels, halExtra->num_levels); 56527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent // FIXME: transfer buffer ownership. should have a method for that in hidl_vec 56627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent extra->levels.resize(halExtra->num_levels); 56727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent delete[] levels; 56827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 56927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 5703acaa668c102cf096a9e3bc540d7a74ca3ac5c36Mikhail NaganovISoundTriggerHw *HIDL_FETCH_ISoundTriggerHw(const char* /* name */) 57127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent{ 5723acaa668c102cf096a9e3bc540d7a74ca3ac5c36Mikhail Naganov return new SoundTriggerHalImpl(); 57327ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} 57427ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} // namespace implementation 57527ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} // namespace V2_0 57627ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} // namespace soundtrigger 57727ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} // namespace hardware 57827ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent} // namespace android 57927ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 58027ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 58127ef4d872d9f6bbbc62d03b807cae694a3c6e2e8Eric Laurent 582