From b7a11d83f749ad0200778c4815e907d011d4b5d3 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 18 Apr 2014 17:40:41 -0700 Subject: add sound trigger native service Change-Id: I0cd954c1c7d28a334e786d0004431d4f6a1227ec --- soundtrigger/SoundTrigger.cpp | 253 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 soundtrigger/SoundTrigger.cpp (limited to 'soundtrigger/SoundTrigger.cpp') diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp new file mode 100644 index 0000000..e43acd0 --- /dev/null +++ b/soundtrigger/SoundTrigger.cpp @@ -0,0 +1,253 @@ +/* +** +** Copyright (C) 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#define LOG_TAG "SoundTrigger" +//#define LOG_NDEBUG 0 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace android { + +namespace { + sp gSoundTriggerHwService; + const int kSoundTriggerHwServicePollDelay = 500000; // 0.5s + const char* kSoundTriggerHwServiceName = "media.sound_trigger_hw"; + Mutex gLock; + + class DeathNotifier : public IBinder::DeathRecipient + { + public: + DeathNotifier() { + } + + virtual void binderDied(const wp& who __unused) { + ALOGV("binderDied"); + Mutex::Autolock _l(gLock); + gSoundTriggerHwService.clear(); + ALOGW("Sound trigger service died!"); + } + }; + + sp gDeathNotifier; +}; // namespace anonymous + +const sp& SoundTrigger::getSoundTriggerHwService() +{ + Mutex::Autolock _l(gLock); + if (gSoundTriggerHwService.get() == 0) { + sp sm = defaultServiceManager(); + sp binder; + do { + binder = sm->getService(String16(kSoundTriggerHwServiceName)); + if (binder != 0) { + break; + } + ALOGW("SoundTriggerHwService not published, waiting..."); + usleep(kSoundTriggerHwServicePollDelay); + } while(true); + if (gDeathNotifier == NULL) { + gDeathNotifier = new DeathNotifier(); + } + binder->linkToDeath(gDeathNotifier); + gSoundTriggerHwService = interface_cast(binder); + } + ALOGE_IF(gSoundTriggerHwService == 0, "no SoundTriggerHwService!?"); + return gSoundTriggerHwService; +} + +// Static methods +status_t SoundTrigger::listModules(struct sound_trigger_module_descriptor *modules, + uint32_t *numModules) +{ + ALOGV("listModules()"); + const sp& service = getSoundTriggerHwService(); + if (service == 0) { + return NO_INIT; + } + return service->listModules(modules, numModules); +} + +sp SoundTrigger::attach(const sound_trigger_module_handle_t module, + const sp& callback) +{ + ALOGV("attach()"); + sp soundTrigger; + const sp& service = getSoundTriggerHwService(); + if (service == 0) { + return soundTrigger; + } + soundTrigger = new SoundTrigger(module, callback); + status_t status = service->attach(module, soundTrigger, soundTrigger->mISoundTrigger); + + if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) { + soundTrigger->mISoundTrigger->asBinder()->linkToDeath(soundTrigger); + } else { + ALOGW("Error %d connecting to sound trigger service", status); + soundTrigger.clear(); + } + return soundTrigger; +} + + +// SoundTrigger +SoundTrigger::SoundTrigger(sound_trigger_module_handle_t module, + const sp& callback) + : mModule(module), mCallback(callback) +{ +} + +SoundTrigger::~SoundTrigger() +{ + if (mISoundTrigger != 0) { + mISoundTrigger->detach(); + } +} + + +void SoundTrigger::detach() { + ALOGV("detach()"); + Mutex::Autolock _l(mLock); + mCallback.clear(); + if (mISoundTrigger != 0) { + mISoundTrigger->detach(); + mISoundTrigger->asBinder()->unlinkToDeath(this); + mISoundTrigger = 0; + } +} + +status_t SoundTrigger::loadSoundModel(const sp& modelMemory, + sound_model_handle_t *handle) +{ + Mutex::Autolock _l(mLock); + if (mISoundTrigger == 0) { + return NO_INIT; + } + + return mISoundTrigger->loadSoundModel(modelMemory, handle); +} + +status_t SoundTrigger::unloadSoundModel(sound_model_handle_t handle) +{ + Mutex::Autolock _l(mLock); + if (mISoundTrigger == 0) { + return NO_INIT; + } + return mISoundTrigger->unloadSoundModel(handle); +} + +status_t SoundTrigger::startRecognition(sound_model_handle_t handle, + const sp& dataMemory) +{ + Mutex::Autolock _l(mLock); + if (mISoundTrigger == 0) { + return NO_INIT; + } + return mISoundTrigger->startRecognition(handle, dataMemory); +} + +status_t SoundTrigger::stopRecognition(sound_model_handle_t handle) +{ + Mutex::Autolock _l(mLock); + if (mISoundTrigger == 0) { + return NO_INIT; + } + return mISoundTrigger->stopRecognition(handle); +} + +// BpSoundTriggerClient +void SoundTrigger::onRecognitionEvent(const sp& eventMemory) +{ + Mutex::Autolock _l(mLock); + if (eventMemory == 0 || eventMemory->pointer() == NULL) { + return; + } + + if (mCallback != 0) { + mCallback->onRecognitionEvent( + (struct sound_trigger_recognition_event *)eventMemory->pointer()); + } +} + + +//IBinder::DeathRecipient +void SoundTrigger::binderDied(const wp& who __unused) { + Mutex::Autolock _l(mLock); + ALOGW("SoundTrigger server binder Died "); + mISoundTrigger = 0; + if (mCallback != 0) { + mCallback->onServiceDied(); + } +} + +status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_uuid_t *guid) +{ + if (str == NULL || guid == NULL) { + return BAD_VALUE; + } + + int tmp[10]; + + if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", + tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) { + return BAD_VALUE; + } + guid->timeLow = (uint32_t)tmp[0]; + guid->timeMid = (uint16_t)tmp[1]; + guid->timeHiAndVersion = (uint16_t)tmp[2]; + guid->clockSeq = (uint16_t)tmp[3]; + guid->node[0] = (uint8_t)tmp[4]; + guid->node[1] = (uint8_t)tmp[5]; + guid->node[2] = (uint8_t)tmp[6]; + guid->node[3] = (uint8_t)tmp[7]; + guid->node[4] = (uint8_t)tmp[8]; + guid->node[5] = (uint8_t)tmp[9]; + + return NO_ERROR; +} + +status_t SoundTrigger::guidToString(const sound_trigger_uuid_t *guid, char *str, size_t maxLen) +{ + if (guid == NULL || str == NULL) { + return BAD_VALUE; + } + + snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", + guid->timeLow, + guid->timeMid, + guid->timeHiAndVersion, + guid->clockSeq, + guid->node[0], + guid->node[1], + guid->node[2], + guid->node[3], + guid->node[4], + guid->node[5]); + + return NO_ERROR; +} + +}; // namespace android -- cgit v1.1