blob: d1eb3677634419163b9dc30106882464e350c043 [file] [log] [blame]
Eric Laurentb7a11d82014-04-18 17:40:41 -07001/*
2**
3** Copyright (C) 2014, The Android Open Source Project
4**
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
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
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.
16*/
17
18#define LOG_TAG "SoundTrigger"
19//#define LOG_NDEBUG 0
20
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>
26
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>
32
33namespace android {
34
35namespace {
36 sp<ISoundTriggerHwService> gSoundTriggerHwService;
37 const int kSoundTriggerHwServicePollDelay = 500000; // 0.5s
38 const char* kSoundTriggerHwServiceName = "media.sound_trigger_hw";
39 Mutex gLock;
40
41 class DeathNotifier : public IBinder::DeathRecipient
42 {
43 public:
44 DeathNotifier() {
45 }
46
47 virtual void binderDied(const wp<IBinder>& who __unused) {
48 ALOGV("binderDied");
49 Mutex::Autolock _l(gLock);
50 gSoundTriggerHwService.clear();
51 ALOGW("Sound trigger service died!");
52 }
53 };
54
55 sp<DeathNotifier> gDeathNotifier;
56}; // namespace anonymous
57
Eric Laurent37698712016-09-07 16:58:39 -070058const sp<ISoundTriggerHwService> SoundTrigger::getSoundTriggerHwService()
Eric Laurentb7a11d82014-04-18 17:40:41 -070059{
60 Mutex::Autolock _l(gLock);
61 if (gSoundTriggerHwService.get() == 0) {
62 sp<IServiceManager> sm = defaultServiceManager();
63 sp<IBinder> binder;
64 do {
65 binder = sm->getService(String16(kSoundTriggerHwServiceName));
66 if (binder != 0) {
67 break;
68 }
69 ALOGW("SoundTriggerHwService not published, waiting...");
70 usleep(kSoundTriggerHwServicePollDelay);
71 } while(true);
72 if (gDeathNotifier == NULL) {
73 gDeathNotifier = new DeathNotifier();
74 }
75 binder->linkToDeath(gDeathNotifier);
76 gSoundTriggerHwService = interface_cast<ISoundTriggerHwService>(binder);
77 }
78 ALOGE_IF(gSoundTriggerHwService == 0, "no SoundTriggerHwService!?");
79 return gSoundTriggerHwService;
80}
81
82// Static methods
83status_t SoundTrigger::listModules(struct sound_trigger_module_descriptor *modules,
84 uint32_t *numModules)
85{
86 ALOGV("listModules()");
Eric Laurent37698712016-09-07 16:58:39 -070087 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
Eric Laurentb7a11d82014-04-18 17:40:41 -070088 if (service == 0) {
89 return NO_INIT;
90 }
91 return service->listModules(modules, numModules);
92}
93
94sp<SoundTrigger> SoundTrigger::attach(const sound_trigger_module_handle_t module,
95 const sp<SoundTriggerCallback>& callback)
96{
97 ALOGV("attach()");
98 sp<SoundTrigger> soundTrigger;
Eric Laurent37698712016-09-07 16:58:39 -070099 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
Eric Laurentb7a11d82014-04-18 17:40:41 -0700100 if (service == 0) {
101 return soundTrigger;
102 }
103 soundTrigger = new SoundTrigger(module, callback);
104 status_t status = service->attach(module, soundTrigger, soundTrigger->mISoundTrigger);
105
106 if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) {
Marco Nelissen06b46062014-11-14 07:58:25 -0800107 IInterface::asBinder(soundTrigger->mISoundTrigger)->linkToDeath(soundTrigger);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700108 } else {
109 ALOGW("Error %d connecting to sound trigger service", status);
110 soundTrigger.clear();
111 }
112 return soundTrigger;
113}
114
115
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700116status_t SoundTrigger::setCaptureState(bool active)
117{
118 ALOGV("setCaptureState(%d)", active);
Eric Laurent37698712016-09-07 16:58:39 -0700119 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700120 if (service == 0) {
121 return NO_INIT;
122 }
123 return service->setCaptureState(active);
124}
125
Eric Laurentb7a11d82014-04-18 17:40:41 -0700126// SoundTrigger
Colin Cross6f51c152017-04-28 12:46:17 -0700127SoundTrigger::SoundTrigger(sound_trigger_module_handle_t /*module*/,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700128 const sp<SoundTriggerCallback>& callback)
Colin Cross6f51c152017-04-28 12:46:17 -0700129 : mCallback(callback)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700130{
131}
132
133SoundTrigger::~SoundTrigger()
134{
135 if (mISoundTrigger != 0) {
136 mISoundTrigger->detach();
137 }
138}
139
140
141void SoundTrigger::detach() {
142 ALOGV("detach()");
143 Mutex::Autolock _l(mLock);
144 mCallback.clear();
145 if (mISoundTrigger != 0) {
146 mISoundTrigger->detach();
Marco Nelissen06b46062014-11-14 07:58:25 -0800147 IInterface::asBinder(mISoundTrigger)->unlinkToDeath(this);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700148 mISoundTrigger = 0;
149 }
150}
151
152status_t SoundTrigger::loadSoundModel(const sp<IMemory>& modelMemory,
153 sound_model_handle_t *handle)
154{
155 Mutex::Autolock _l(mLock);
156 if (mISoundTrigger == 0) {
157 return NO_INIT;
158 }
159
160 return mISoundTrigger->loadSoundModel(modelMemory, handle);
161}
162
163status_t SoundTrigger::unloadSoundModel(sound_model_handle_t handle)
164{
165 Mutex::Autolock _l(mLock);
166 if (mISoundTrigger == 0) {
167 return NO_INIT;
168 }
169 return mISoundTrigger->unloadSoundModel(handle);
170}
171
172status_t SoundTrigger::startRecognition(sound_model_handle_t handle,
173 const sp<IMemory>& dataMemory)
174{
175 Mutex::Autolock _l(mLock);
176 if (mISoundTrigger == 0) {
177 return NO_INIT;
178 }
179 return mISoundTrigger->startRecognition(handle, dataMemory);
180}
181
182status_t SoundTrigger::stopRecognition(sound_model_handle_t handle)
183{
184 Mutex::Autolock _l(mLock);
185 if (mISoundTrigger == 0) {
186 return NO_INIT;
187 }
188 return mISoundTrigger->stopRecognition(handle);
189}
190
mike dooley6e189b12018-11-07 15:44:37 +0100191status_t SoundTrigger::getModelState(sound_model_handle_t handle)
Michael Dooley67e3d412018-10-16 19:51:16 +0000192{
193 Mutex::Autolock _l(mLock);
194 if (mISoundTrigger == 0) {
195 return NO_INIT;
196 }
mike dooley6e189b12018-11-07 15:44:37 +0100197 return mISoundTrigger->getModelState(handle);
Michael Dooley67e3d412018-10-16 19:51:16 +0000198}
199
Eric Laurentb7a11d82014-04-18 17:40:41 -0700200// BpSoundTriggerClient
201void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
202{
203 Mutex::Autolock _l(mLock);
204 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
205 return;
206 }
207
208 if (mCallback != 0) {
209 mCallback->onRecognitionEvent(
210 (struct sound_trigger_recognition_event *)eventMemory->pointer());
211 }
212}
213
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700214void SoundTrigger::onSoundModelEvent(const sp<IMemory>& eventMemory)
215{
216 Mutex::Autolock _l(mLock);
217 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
218 return;
219 }
220
221 if (mCallback != 0) {
222 mCallback->onSoundModelEvent(
223 (struct sound_trigger_model_event *)eventMemory->pointer());
224 }
225}
226
227void SoundTrigger::onServiceStateChange(const sp<IMemory>& eventMemory)
228{
229 Mutex::Autolock _l(mLock);
230 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
231 return;
232 }
233
234 if (mCallback != 0) {
235 mCallback->onServiceStateChange(
236 *((sound_trigger_service_state_t *)eventMemory->pointer()));
237 }
238}
Eric Laurentb7a11d82014-04-18 17:40:41 -0700239
240//IBinder::DeathRecipient
241void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {
242 Mutex::Autolock _l(mLock);
243 ALOGW("SoundTrigger server binder Died ");
244 mISoundTrigger = 0;
245 if (mCallback != 0) {
246 mCallback->onServiceDied();
247 }
248}
249
250status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_uuid_t *guid)
251{
252 if (str == NULL || guid == NULL) {
253 return BAD_VALUE;
254 }
255
256 int tmp[10];
257
258 if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
259 tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
260 return BAD_VALUE;
261 }
262 guid->timeLow = (uint32_t)tmp[0];
263 guid->timeMid = (uint16_t)tmp[1];
264 guid->timeHiAndVersion = (uint16_t)tmp[2];
265 guid->clockSeq = (uint16_t)tmp[3];
266 guid->node[0] = (uint8_t)tmp[4];
267 guid->node[1] = (uint8_t)tmp[5];
268 guid->node[2] = (uint8_t)tmp[6];
269 guid->node[3] = (uint8_t)tmp[7];
270 guid->node[4] = (uint8_t)tmp[8];
271 guid->node[5] = (uint8_t)tmp[9];
272
273 return NO_ERROR;
274}
275
276status_t SoundTrigger::guidToString(const sound_trigger_uuid_t *guid, char *str, size_t maxLen)
277{
278 if (guid == NULL || str == NULL) {
279 return BAD_VALUE;
280 }
281
282 snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
283 guid->timeLow,
284 guid->timeMid,
285 guid->timeHiAndVersion,
286 guid->clockSeq,
287 guid->node[0],
288 guid->node[1],
289 guid->node[2],
290 guid->node[3],
291 guid->node[4],
292 guid->node[5]);
293
294 return NO_ERROR;
295}
296
297}; // namespace android