blob: 021697b9ae3c7484fd4f3a24e15440ca125f942a [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
jiabin68e0df72019-03-18 17:55:35 -070083status_t SoundTrigger::listModules(const String16& opPackageName,
84 struct sound_trigger_module_descriptor *modules,
85 uint32_t *numModules)
Eric Laurentb7a11d82014-04-18 17:40:41 -070086{
87 ALOGV("listModules()");
Eric Laurent37698712016-09-07 16:58:39 -070088 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
Eric Laurentb7a11d82014-04-18 17:40:41 -070089 if (service == 0) {
90 return NO_INIT;
91 }
jiabin68e0df72019-03-18 17:55:35 -070092 return service->listModules(opPackageName, modules, numModules);
Eric Laurentb7a11d82014-04-18 17:40:41 -070093}
94
jiabin68e0df72019-03-18 17:55:35 -070095sp<SoundTrigger> SoundTrigger::attach(const String16& opPackageName,
96 const sound_trigger_module_handle_t module,
97 const sp<SoundTriggerCallback>& callback)
Eric Laurentb7a11d82014-04-18 17:40:41 -070098{
99 ALOGV("attach()");
100 sp<SoundTrigger> soundTrigger;
Eric Laurent37698712016-09-07 16:58:39 -0700101 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
Eric Laurentb7a11d82014-04-18 17:40:41 -0700102 if (service == 0) {
103 return soundTrigger;
104 }
105 soundTrigger = new SoundTrigger(module, callback);
jiabin68e0df72019-03-18 17:55:35 -0700106 status_t status = service->attach(opPackageName, module, soundTrigger,
107 soundTrigger->mISoundTrigger);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700108
109 if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) {
Marco Nelissen06b46062014-11-14 07:58:25 -0800110 IInterface::asBinder(soundTrigger->mISoundTrigger)->linkToDeath(soundTrigger);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700111 } else {
112 ALOGW("Error %d connecting to sound trigger service", status);
113 soundTrigger.clear();
114 }
115 return soundTrigger;
116}
117
118
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700119status_t SoundTrigger::setCaptureState(bool active)
120{
121 ALOGV("setCaptureState(%d)", active);
Eric Laurent37698712016-09-07 16:58:39 -0700122 const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700123 if (service == 0) {
124 return NO_INIT;
125 }
126 return service->setCaptureState(active);
127}
128
Eric Laurentb7a11d82014-04-18 17:40:41 -0700129// SoundTrigger
Colin Cross6f51c152017-04-28 12:46:17 -0700130SoundTrigger::SoundTrigger(sound_trigger_module_handle_t /*module*/,
Eric Laurentb7a11d82014-04-18 17:40:41 -0700131 const sp<SoundTriggerCallback>& callback)
Colin Cross6f51c152017-04-28 12:46:17 -0700132 : mCallback(callback)
Eric Laurentb7a11d82014-04-18 17:40:41 -0700133{
134}
135
136SoundTrigger::~SoundTrigger()
137{
138 if (mISoundTrigger != 0) {
139 mISoundTrigger->detach();
140 }
141}
142
143
144void SoundTrigger::detach() {
145 ALOGV("detach()");
146 Mutex::Autolock _l(mLock);
147 mCallback.clear();
148 if (mISoundTrigger != 0) {
149 mISoundTrigger->detach();
Marco Nelissen06b46062014-11-14 07:58:25 -0800150 IInterface::asBinder(mISoundTrigger)->unlinkToDeath(this);
Eric Laurentb7a11d82014-04-18 17:40:41 -0700151 mISoundTrigger = 0;
152 }
153}
154
155status_t SoundTrigger::loadSoundModel(const sp<IMemory>& modelMemory,
156 sound_model_handle_t *handle)
157{
158 Mutex::Autolock _l(mLock);
159 if (mISoundTrigger == 0) {
160 return NO_INIT;
161 }
162
163 return mISoundTrigger->loadSoundModel(modelMemory, handle);
164}
165
166status_t SoundTrigger::unloadSoundModel(sound_model_handle_t handle)
167{
168 Mutex::Autolock _l(mLock);
169 if (mISoundTrigger == 0) {
170 return NO_INIT;
171 }
172 return mISoundTrigger->unloadSoundModel(handle);
173}
174
175status_t SoundTrigger::startRecognition(sound_model_handle_t handle,
176 const sp<IMemory>& dataMemory)
177{
178 Mutex::Autolock _l(mLock);
179 if (mISoundTrigger == 0) {
180 return NO_INIT;
181 }
182 return mISoundTrigger->startRecognition(handle, dataMemory);
183}
184
185status_t SoundTrigger::stopRecognition(sound_model_handle_t handle)
186{
187 Mutex::Autolock _l(mLock);
188 if (mISoundTrigger == 0) {
189 return NO_INIT;
190 }
191 return mISoundTrigger->stopRecognition(handle);
192}
193
mike dooley6e189b12018-11-07 15:44:37 +0100194status_t SoundTrigger::getModelState(sound_model_handle_t handle)
Michael Dooley67e3d412018-10-16 19:51:16 +0000195{
196 Mutex::Autolock _l(mLock);
197 if (mISoundTrigger == 0) {
198 return NO_INIT;
199 }
mike dooley6e189b12018-11-07 15:44:37 +0100200 return mISoundTrigger->getModelState(handle);
Michael Dooley67e3d412018-10-16 19:51:16 +0000201}
202
Nicholas Ambur41947e22019-10-01 11:53:40 -0700203status_t SoundTrigger::setParameter(sound_model_handle_t handle,
204 sound_trigger_model_parameter_t param, int32_t value)
205{
206 Mutex::Autolock _l(mLock);
207 if (mISoundTrigger == 0) {
208 return NO_INIT;
209 }
210 return mISoundTrigger->setParameter(handle, param, value);
211}
212
213status_t SoundTrigger::getParameter(sound_model_handle_t handle,
214 sound_trigger_model_parameter_t param, int32_t* value)
215{
216 Mutex::Autolock _l(mLock);
217 if (mISoundTrigger == 0) {
218 return NO_INIT;
219 }
220 return mISoundTrigger->getParameter(handle, param, value);
221}
222
223status_t SoundTrigger::queryParameter(sound_model_handle_t handle,
224 sound_trigger_model_parameter_t param,
225 sound_trigger_model_parameter_range_t* param_range)
226{
227 Mutex::Autolock _l(mLock);
228 if (mISoundTrigger == 0) {
229 return NO_INIT;
230 }
231 return mISoundTrigger->queryParameter(handle, param, param_range);
232}
233
Eric Laurentb7a11d82014-04-18 17:40:41 -0700234// BpSoundTriggerClient
235void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
236{
237 Mutex::Autolock _l(mLock);
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700238 if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
Eric Laurentb7a11d82014-04-18 17:40:41 -0700239 return;
240 }
241
242 if (mCallback != 0) {
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700243 // Memory is coming from a trusted process.
Eric Laurentb7a11d82014-04-18 17:40:41 -0700244 mCallback->onRecognitionEvent(
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700245 (struct sound_trigger_recognition_event *)eventMemory->unsecurePointer());
Eric Laurentb7a11d82014-04-18 17:40:41 -0700246 }
247}
248
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700249void SoundTrigger::onSoundModelEvent(const sp<IMemory>& eventMemory)
250{
251 Mutex::Autolock _l(mLock);
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700252 if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700253 return;
254 }
255
256 if (mCallback != 0) {
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700257 // Memory is coming from a trusted process.
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700258 mCallback->onSoundModelEvent(
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700259 (struct sound_trigger_model_event *)eventMemory->unsecurePointer());
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700260 }
261}
262
263void SoundTrigger::onServiceStateChange(const sp<IMemory>& eventMemory)
264{
265 Mutex::Autolock _l(mLock);
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700266 if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700267 return;
268 }
269
270 if (mCallback != 0) {
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700271 // Memory is coming from a trusted process.
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700272 mCallback->onServiceStateChange(
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700273 *((sound_trigger_service_state_t *)eventMemory->unsecurePointer()));
Eric Laurentdf3dc7e2014-07-27 18:39:40 -0700274 }
275}
Eric Laurentb7a11d82014-04-18 17:40:41 -0700276
277//IBinder::DeathRecipient
278void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {
279 Mutex::Autolock _l(mLock);
280 ALOGW("SoundTrigger server binder Died ");
281 mISoundTrigger = 0;
282 if (mCallback != 0) {
283 mCallback->onServiceDied();
284 }
285}
286
287status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_uuid_t *guid)
288{
289 if (str == NULL || guid == NULL) {
290 return BAD_VALUE;
291 }
292
293 int tmp[10];
294
295 if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
296 tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
297 return BAD_VALUE;
298 }
299 guid->timeLow = (uint32_t)tmp[0];
300 guid->timeMid = (uint16_t)tmp[1];
301 guid->timeHiAndVersion = (uint16_t)tmp[2];
302 guid->clockSeq = (uint16_t)tmp[3];
303 guid->node[0] = (uint8_t)tmp[4];
304 guid->node[1] = (uint8_t)tmp[5];
305 guid->node[2] = (uint8_t)tmp[6];
306 guid->node[3] = (uint8_t)tmp[7];
307 guid->node[4] = (uint8_t)tmp[8];
308 guid->node[5] = (uint8_t)tmp[9];
309
310 return NO_ERROR;
311}
312
313status_t SoundTrigger::guidToString(const sound_trigger_uuid_t *guid, char *str, size_t maxLen)
314{
315 if (guid == NULL || str == NULL) {
316 return BAD_VALUE;
317 }
318
319 snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
320 guid->timeLow,
321 guid->timeMid,
322 guid->timeHiAndVersion,
323 guid->clockSeq,
324 guid->node[0],
325 guid->node[1],
326 guid->node[2],
327 guid->node[3],
328 guid->node[4],
329 guid->node[5]);
330
331 return NO_ERROR;
332}
333
334}; // namespace android