OSDN Git Service

CameraBase: Don't return an sp<> by reference am: 4b49489c12 am: 8c32699ceb
[android-x86/frameworks-av.git] / soundtrigger / SoundTrigger.cpp
1 /*
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
33 namespace android {
34
35 namespace {
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
58 const sp<ISoundTriggerHwService> SoundTrigger::getSoundTriggerHwService()
59 {
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
83 status_t SoundTrigger::listModules(struct sound_trigger_module_descriptor *modules,
84                                  uint32_t *numModules)
85 {
86     ALOGV("listModules()");
87     const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
88     if (service == 0) {
89         return NO_INIT;
90     }
91     return service->listModules(modules, numModules);
92 }
93
94 sp<SoundTrigger> SoundTrigger::attach(const sound_trigger_module_handle_t module,
95                                             const sp<SoundTriggerCallback>& callback)
96 {
97     ALOGV("attach()");
98     sp<SoundTrigger> soundTrigger;
99     const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
100     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) {
107         soundTrigger->mISoundTrigger->asBinder()->linkToDeath(soundTrigger);
108     } else {
109         ALOGW("Error %d connecting to sound trigger service", status);
110         soundTrigger.clear();
111     }
112     return soundTrigger;
113 }
114
115
116 status_t SoundTrigger::setCaptureState(bool active)
117 {
118     ALOGV("setCaptureState(%d)", active);
119     const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
120     if (service == 0) {
121         return NO_INIT;
122     }
123     return service->setCaptureState(active);
124 }
125
126 // SoundTrigger
127 SoundTrigger::SoundTrigger(sound_trigger_module_handle_t module,
128                                  const sp<SoundTriggerCallback>& callback)
129     : mModule(module), mCallback(callback)
130 {
131 }
132
133 SoundTrigger::~SoundTrigger()
134 {
135     if (mISoundTrigger != 0) {
136         mISoundTrigger->detach();
137     }
138 }
139
140
141 void SoundTrigger::detach() {
142     ALOGV("detach()");
143     Mutex::Autolock _l(mLock);
144     mCallback.clear();
145     if (mISoundTrigger != 0) {
146         mISoundTrigger->detach();
147         mISoundTrigger->asBinder()->unlinkToDeath(this);
148         mISoundTrigger = 0;
149     }
150 }
151
152 status_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
163 status_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
172 status_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
182 status_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
191 // BpSoundTriggerClient
192 void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
193 {
194     Mutex::Autolock _l(mLock);
195     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
196         return;
197     }
198
199     if (mCallback != 0) {
200         mCallback->onRecognitionEvent(
201                 (struct sound_trigger_recognition_event *)eventMemory->pointer());
202     }
203 }
204
205 void SoundTrigger::onSoundModelEvent(const sp<IMemory>& eventMemory)
206 {
207     Mutex::Autolock _l(mLock);
208     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
209         return;
210     }
211
212     if (mCallback != 0) {
213         mCallback->onSoundModelEvent(
214                 (struct sound_trigger_model_event *)eventMemory->pointer());
215     }
216 }
217
218 void SoundTrigger::onServiceStateChange(const sp<IMemory>& eventMemory)
219 {
220     Mutex::Autolock _l(mLock);
221     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
222         return;
223     }
224
225     if (mCallback != 0) {
226         mCallback->onServiceStateChange(
227                 *((sound_trigger_service_state_t *)eventMemory->pointer()));
228     }
229 }
230
231 //IBinder::DeathRecipient
232 void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {
233     Mutex::Autolock _l(mLock);
234     ALOGW("SoundTrigger server binder Died ");
235     mISoundTrigger = 0;
236     if (mCallback != 0) {
237         mCallback->onServiceDied();
238     }
239 }
240
241 status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_uuid_t *guid)
242 {
243     if (str == NULL || guid == NULL) {
244         return BAD_VALUE;
245     }
246
247     int tmp[10];
248
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) {
251         return BAD_VALUE;
252     }
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];
263
264     return NO_ERROR;
265 }
266
267 status_t SoundTrigger::guidToString(const sound_trigger_uuid_t *guid, char *str, size_t maxLen)
268 {
269     if (guid == NULL || str == NULL) {
270         return BAD_VALUE;
271     }
272
273     snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
274             guid->timeLow,
275             guid->timeMid,
276             guid->timeHiAndVersion,
277             guid->clockSeq,
278             guid->node[0],
279             guid->node[1],
280             guid->node[2],
281             guid->node[3],
282             guid->node[4],
283             guid->node[5]);
284
285     return NO_ERROR;
286 }
287
288 }; // namespace android