3 ** Copyright (C) 2014, The Android Open Source Project
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
9 ** http://www.apache.org/licenses/LICENSE-2.0
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
18 #define LOG_TAG "SoundTrigger"
19 //#define LOG_NDEBUG 0
21 #include <utils/Log.h>
22 #include <utils/threads.h>
23 #include <binder/IPCThreadState.h>
24 #include <binder/IServiceManager.h>
25 #include <binder/IMemory.h>
27 #include <soundtrigger/SoundTrigger.h>
28 #include <soundtrigger/ISoundTrigger.h>
29 #include <soundtrigger/ISoundTriggerHwService.h>
30 #include <soundtrigger/ISoundTriggerClient.h>
31 #include <soundtrigger/SoundTriggerCallback.h>
36 sp<ISoundTriggerHwService> gSoundTriggerHwService;
37 const int kSoundTriggerHwServicePollDelay = 500000; // 0.5s
38 const char* kSoundTriggerHwServiceName = "media.sound_trigger_hw";
41 class DeathNotifier : public IBinder::DeathRecipient
47 virtual void binderDied(const wp<IBinder>& who __unused) {
49 Mutex::Autolock _l(gLock);
50 gSoundTriggerHwService.clear();
51 ALOGW("Sound trigger service died!");
55 sp<DeathNotifier> gDeathNotifier;
56 }; // namespace anonymous
58 const sp<ISoundTriggerHwService> SoundTrigger::getSoundTriggerHwService()
60 Mutex::Autolock _l(gLock);
61 if (gSoundTriggerHwService.get() == 0) {
62 sp<IServiceManager> sm = defaultServiceManager();
65 binder = sm->getService(String16(kSoundTriggerHwServiceName));
69 ALOGW("SoundTriggerHwService not published, waiting...");
70 usleep(kSoundTriggerHwServicePollDelay);
72 if (gDeathNotifier == NULL) {
73 gDeathNotifier = new DeathNotifier();
75 binder->linkToDeath(gDeathNotifier);
76 gSoundTriggerHwService = interface_cast<ISoundTriggerHwService>(binder);
78 ALOGE_IF(gSoundTriggerHwService == 0, "no SoundTriggerHwService!?");
79 return gSoundTriggerHwService;
83 status_t SoundTrigger::listModules(struct sound_trigger_module_descriptor *modules,
86 ALOGV("listModules()");
87 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
91 return service->listModules(modules, numModules);
94 sp<SoundTrigger> SoundTrigger::attach(const sound_trigger_module_handle_t module,
95 const sp<SoundTriggerCallback>& callback)
98 sp<SoundTrigger> soundTrigger;
99 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
103 soundTrigger = new SoundTrigger(module, callback);
104 status_t status = service->attach(module, soundTrigger, soundTrigger->mISoundTrigger);
106 if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) {
107 soundTrigger->mISoundTrigger->asBinder()->linkToDeath(soundTrigger);
109 ALOGW("Error %d connecting to sound trigger service", status);
110 soundTrigger.clear();
116 status_t SoundTrigger::setCaptureState(bool active)
118 ALOGV("setCaptureState(%d)", active);
119 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
123 return service->setCaptureState(active);
127 SoundTrigger::SoundTrigger(sound_trigger_module_handle_t module,
128 const sp<SoundTriggerCallback>& callback)
129 : mModule(module), mCallback(callback)
133 SoundTrigger::~SoundTrigger()
135 if (mISoundTrigger != 0) {
136 mISoundTrigger->detach();
141 void SoundTrigger::detach() {
143 Mutex::Autolock _l(mLock);
145 if (mISoundTrigger != 0) {
146 mISoundTrigger->detach();
147 mISoundTrigger->asBinder()->unlinkToDeath(this);
152 status_t SoundTrigger::loadSoundModel(const sp<IMemory>& modelMemory,
153 sound_model_handle_t *handle)
155 Mutex::Autolock _l(mLock);
156 if (mISoundTrigger == 0) {
160 return mISoundTrigger->loadSoundModel(modelMemory, handle);
163 status_t SoundTrigger::unloadSoundModel(sound_model_handle_t handle)
165 Mutex::Autolock _l(mLock);
166 if (mISoundTrigger == 0) {
169 return mISoundTrigger->unloadSoundModel(handle);
172 status_t SoundTrigger::startRecognition(sound_model_handle_t handle,
173 const sp<IMemory>& dataMemory)
175 Mutex::Autolock _l(mLock);
176 if (mISoundTrigger == 0) {
179 return mISoundTrigger->startRecognition(handle, dataMemory);
182 status_t SoundTrigger::stopRecognition(sound_model_handle_t handle)
184 Mutex::Autolock _l(mLock);
185 if (mISoundTrigger == 0) {
188 return mISoundTrigger->stopRecognition(handle);
191 // BpSoundTriggerClient
192 void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
194 Mutex::Autolock _l(mLock);
195 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
199 if (mCallback != 0) {
200 mCallback->onRecognitionEvent(
201 (struct sound_trigger_recognition_event *)eventMemory->pointer());
205 void SoundTrigger::onSoundModelEvent(const sp<IMemory>& eventMemory)
207 Mutex::Autolock _l(mLock);
208 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
212 if (mCallback != 0) {
213 mCallback->onSoundModelEvent(
214 (struct sound_trigger_model_event *)eventMemory->pointer());
218 void SoundTrigger::onServiceStateChange(const sp<IMemory>& eventMemory)
220 Mutex::Autolock _l(mLock);
221 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
225 if (mCallback != 0) {
226 mCallback->onServiceStateChange(
227 *((sound_trigger_service_state_t *)eventMemory->pointer()));
231 //IBinder::DeathRecipient
232 void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {
233 Mutex::Autolock _l(mLock);
234 ALOGW("SoundTrigger server binder Died ");
236 if (mCallback != 0) {
237 mCallback->onServiceDied();
241 status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_uuid_t *guid)
243 if (str == NULL || guid == NULL) {
249 if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
250 tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
253 guid->timeLow = (uint32_t)tmp[0];
254 guid->timeMid = (uint16_t)tmp[1];
255 guid->timeHiAndVersion = (uint16_t)tmp[2];
256 guid->clockSeq = (uint16_t)tmp[3];
257 guid->node[0] = (uint8_t)tmp[4];
258 guid->node[1] = (uint8_t)tmp[5];
259 guid->node[2] = (uint8_t)tmp[6];
260 guid->node[3] = (uint8_t)tmp[7];
261 guid->node[4] = (uint8_t)tmp[8];
262 guid->node[5] = (uint8_t)tmp[9];
267 status_t SoundTrigger::guidToString(const sound_trigger_uuid_t *guid, char *str, size_t maxLen)
269 if (guid == NULL || str == NULL) {
273 snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
276 guid->timeHiAndVersion,
288 }; // namespace android