blob: 69e991d261abb933993d3ece5a827983d59350a9 [file] [log] [blame]
Eric Laurent60b62bc2014-04-18 17:50:49 -07001/*
2**
3** Copyright 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_NDEBUG 0
19#define LOG_TAG "SoundTrigger-JNI"
20#include <utils/Log.h>
21
22#include "jni.h"
23#include "JNIHelp.h"
24#include "android_runtime/AndroidRuntime.h"
25#include <system/sound_trigger.h>
26#include <soundtrigger/SoundTriggerCallback.h>
27#include <soundtrigger/SoundTrigger.h>
28#include <utils/RefBase.h>
29#include <utils/Vector.h>
30#include <binder/IMemory.h>
31#include <binder/MemoryDealer.h>
32
33using namespace android;
34
35static jclass gArrayListClass;
36static struct {
37 jmethodID add;
38} gArrayListMethods;
39
40static const char* const kSoundTriggerClassPathName = "android/hardware/soundtrigger/SoundTrigger";
41static jclass gSoundTriggerClass;
42
43static const char* const kModuleClassPathName = "android/hardware/soundtrigger/SoundTriggerModule";
44static jclass gModuleClass;
45static struct {
46 jfieldID mNativeContext;
47 jfieldID mId;
48} gModuleFields;
49static jmethodID gPostEventFromNative;
50
51static const char* const kModulePropertiesClassPathName =
52 "android/hardware/soundtrigger/SoundTrigger$ModuleProperties";
53static jclass gModulePropertiesClass;
54static jmethodID gModulePropertiesCstor;
55
56static const char* const kSoundModelClassPathName =
57 "android/hardware/soundtrigger/SoundTrigger$SoundModel";
58static jclass gSoundModelClass;
59static struct {
60 jfieldID data;
61} gSoundModelFields;
62
63static const char* const kKeyPhraseClassPathName =
64 "android/hardware/soundtrigger/SoundTrigger$KeyPhrase";
65static jclass gKeyPhraseClass;
66static struct {
67 jfieldID recognitionModes;
68 jfieldID locale;
69 jfieldID text;
70 jfieldID numUsers;
71} gKeyPhraseFields;
72
73static const char* const kKeyPhraseSoundModelClassPathName =
74 "android/hardware/soundtrigger/SoundTrigger$KeyPhraseSoundModel";
75static jclass gKeyPhraseSoundModelClass;
76static struct {
77 jfieldID keyPhrases;
78} gKeyPhraseSoundModelFields;
79
80
81static const char* const kRecognitionEventClassPathName =
82 "android/hardware/soundtrigger/SoundTrigger$RecognitionEvent";
83static jclass gRecognitionEventClass;
84static jmethodID gRecognitionEventCstor;
85
86static const char* const kKeyPhraseRecognitionEventClassPathName =
87 "android/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionEvent";
88static jclass gKeyPhraseRecognitionEventClass;
89static jmethodID gKeyPhraseRecognitionEventCstor;
90
91static const char* const kKeyPhraseRecognitionExtraClassPathName =
92 "android/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionExtra";
93static jclass gKeyPhraseRecognitionExtraClass;
94static jmethodID gKeyPhraseRecognitionExtraCstor;
95
96static Mutex gLock;
97
98enum {
99 SOUNDTRIGGER_STATUS_OK = 0,
100 SOUNDTRIGGER_STATUS_ERROR = INT_MIN,
101 SOUNDTRIGGER_PERMISSION_DENIED = -1,
102 SOUNDTRIGGER_STATUS_NO_INIT = -19,
103 SOUNDTRIGGER_STATUS_BAD_VALUE = -22,
104 SOUNDTRIGGER_STATUS_DEAD_OBJECT = -32,
105 SOUNDTRIGGER_INVALID_OPERATION = -38,
106};
107
108enum {
109 SOUNDTRIGGER_EVENT_RECOGNITION = 1,
110 SOUNDTRIGGER_EVENT_SERVICE_DIED = 2,
111};
112
113// ----------------------------------------------------------------------------
114// ref-counted object for callbacks
115class JNISoundTriggerCallback: public SoundTriggerCallback
116{
117public:
118 JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
119 ~JNISoundTriggerCallback();
120
121 virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event);
122 virtual void onServiceDied();
123
124private:
125 jclass mClass; // Reference to SoundTrigger class
126 jobject mObject; // Weak ref to SoundTrigger Java object to call on
127};
128
129JNISoundTriggerCallback::JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
130{
131
132 // Hold onto the SoundTriggerModule class for use in calling the static method
133 // that posts events to the application thread.
134 jclass clazz = env->GetObjectClass(thiz);
135 if (clazz == NULL) {
136 ALOGE("Can't find class %s", kModuleClassPathName);
137 return;
138 }
139 mClass = (jclass)env->NewGlobalRef(clazz);
140
141 // We use a weak reference so the SoundTriggerModule object can be garbage collected.
142 // The reference is only used as a proxy for callbacks.
143 mObject = env->NewGlobalRef(weak_thiz);
144}
145
146JNISoundTriggerCallback::~JNISoundTriggerCallback()
147{
148 // remove global references
149 JNIEnv *env = AndroidRuntime::getJNIEnv();
150 env->DeleteGlobalRef(mObject);
151 env->DeleteGlobalRef(mClass);
152}
153
154void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognition_event *event)
155{
156 JNIEnv *env = AndroidRuntime::getJNIEnv();
157
158 jobject jEvent;
159
160 jbyteArray jData = NULL;
161 if (event->data_size) {
162 jData = env->NewByteArray(event->data_size);
163 jbyte *nData = env->GetByteArrayElements(jData, NULL);
164 memcpy(nData, (char *)event + event->data_offset, event->data_size);
165 env->ReleaseByteArrayElements(jData, nData, 0);
166 }
167
168 if (event->type == SOUND_MODEL_TYPE_KEYPHRASE) {
169 struct sound_trigger_phrase_recognition_event *phraseEvent =
170 (struct sound_trigger_phrase_recognition_event *)event;
171
172 jobjectArray jExtras = env->NewObjectArray(phraseEvent->num_phrases,
173 gKeyPhraseRecognitionExtraClass, NULL);
174 if (jExtras == NULL) {
175 return;
176 }
177
178 for (size_t i = 0; i < phraseEvent->num_phrases; i++) {
179 jintArray jConfidenceLevels = env->NewIntArray(phraseEvent->phrase_extras[i].num_users);
180 if (jConfidenceLevels == NULL) {
181 return;
182 }
183 jint *nConfidenceLevels = env->GetIntArrayElements(jConfidenceLevels, NULL);
184 memcpy(nConfidenceLevels,
185 phraseEvent->phrase_extras[i].confidence_levels,
186 phraseEvent->phrase_extras[i].num_users * sizeof(int));
187 env->ReleaseIntArrayElements(jConfidenceLevels, nConfidenceLevels, 0);
188 jobject jNewExtra = env->NewObject(gKeyPhraseRecognitionExtraClass,
189 gKeyPhraseRecognitionExtraCstor,
190 jConfidenceLevels,
191 phraseEvent->phrase_extras[i].recognition_modes);
192
193 if (jNewExtra == NULL) {
194 return;
195 }
196 env->SetObjectArrayElement(jExtras, i, jNewExtra);
197
198 }
199 jEvent = env->NewObject(gKeyPhraseRecognitionEventClass, gKeyPhraseRecognitionEventCstor,
200 event->status, event->model, event->capture_available,
201 event->capture_session, event->capture_delay_ms, jData,
202 phraseEvent->key_phrase_in_capture, jExtras);
203 } else {
204 jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor,
205 event->status, event->model, event->capture_available,
206 event->capture_session, event->capture_delay_ms, jData);
207 }
208
209
210 env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
211 SOUNDTRIGGER_EVENT_RECOGNITION, 0, 0, jEvent);
212 if (env->ExceptionCheck()) {
213 ALOGW("An exception occurred while notifying an event.");
214 env->ExceptionClear();
215 }
216}
217
218void JNISoundTriggerCallback::onServiceDied()
219{
220 JNIEnv *env = AndroidRuntime::getJNIEnv();
221
222 env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
223 SOUNDTRIGGER_EVENT_SERVICE_DIED, 0, 0, NULL);
224 if (env->ExceptionCheck()) {
225 ALOGW("An exception occurred while notifying an event.");
226 env->ExceptionClear();
227 }
228}
229
230// ----------------------------------------------------------------------------
231
232static sp<SoundTrigger> getSoundTrigger(JNIEnv* env, jobject thiz)
233{
234 Mutex::Autolock l(gLock);
235 SoundTrigger* const st = (SoundTrigger*)env->GetLongField(thiz,
236 gModuleFields.mNativeContext);
237 return sp<SoundTrigger>(st);
238}
239
240static sp<SoundTrigger> setSoundTrigger(JNIEnv* env, jobject thiz, const sp<SoundTrigger>& module)
241{
242 Mutex::Autolock l(gLock);
243 sp<SoundTrigger> old = (SoundTrigger*)env->GetLongField(thiz,
244 gModuleFields.mNativeContext);
245 if (module.get()) {
246 module->incStrong((void*)setSoundTrigger);
247 }
248 if (old != 0) {
249 old->decStrong((void*)setSoundTrigger);
250 }
251 env->SetLongField(thiz, gModuleFields.mNativeContext, (jlong)module.get());
252 return old;
253}
254
255
256static jint
257android_hardware_SoundTrigger_listModules(JNIEnv *env, jobject clazz,
258 jobject jModules)
259{
260 ALOGV("listModules");
261
262 if (jModules == NULL) {
263 ALOGE("listModules NULL AudioPatch ArrayList");
264 return SOUNDTRIGGER_STATUS_BAD_VALUE;
265 }
266 if (!env->IsInstanceOf(jModules, gArrayListClass)) {
267 ALOGE("listModules not an arraylist");
268 return SOUNDTRIGGER_STATUS_BAD_VALUE;
269 }
270
271 unsigned int numModules = 0;
272 struct sound_trigger_module_descriptor *nModules = NULL;
273
274 status_t status = SoundTrigger::listModules(nModules, &numModules);
275 if (status != NO_ERROR || numModules == 0) {
276 return (jint)status;
277 }
278
279 nModules = (struct sound_trigger_module_descriptor *)
280 calloc(numModules, sizeof(struct sound_trigger_module_descriptor));
281
282 status = SoundTrigger::listModules(nModules, &numModules);
283 ALOGV("listModules SoundTrigger::listModules status %d numModules %d", status, numModules);
284
285 if (status != NO_ERROR) {
286 numModules = 0;
287 }
288
289 for (size_t i = 0; i < numModules; i++) {
290 char str[SOUND_TRIGGER_MAX_STRING_LEN];
291
292 jstring implementor = env->NewStringUTF(nModules[i].properties.implementor);
293 jstring description = env->NewStringUTF(nModules[i].properties.description);
294 SoundTrigger::guidToString(&nModules[i].properties.uuid,
295 str,
296 SOUND_TRIGGER_MAX_STRING_LEN);
297 jstring uuid = env->NewStringUTF(str);
298
299 ALOGV("listModules module %d id %d description %s maxSoundModels %d",
300 i, nModules[i].handle, nModules[i].properties.description,
301 nModules[i].properties.max_sound_models);
302
303 jobject newModuleDesc = env->NewObject(gModulePropertiesClass, gModulePropertiesCstor,
304 nModules[i].handle,
305 implementor, description, uuid,
306 nModules[i].properties.version,
307 nModules[i].properties.max_sound_models,
308 nModules[i].properties.max_key_phrases,
309 nModules[i].properties.max_users,
310 nModules[i].properties.recognition_modes,
311 nModules[i].properties.capture_transition,
312 nModules[i].properties.max_buffer_ms,
313 nModules[i].properties.concurrent_capture,
314 nModules[i].properties.power_consumption_mw);
315
316 env->DeleteLocalRef(implementor);
317 env->DeleteLocalRef(description);
318 env->DeleteLocalRef(uuid);
319 if (newModuleDesc == NULL) {
320 status = SOUNDTRIGGER_STATUS_ERROR;
321 goto exit;
322 }
323 env->CallBooleanMethod(jModules, gArrayListMethods.add, newModuleDesc);
324 }
325
326exit:
327 free(nModules);
328 return (jint) status;
329}
330
331static void
332android_hardware_SoundTrigger_setup(JNIEnv *env, jobject thiz, jobject weak_this)
333{
334 ALOGV("setup");
335
336 sp<JNISoundTriggerCallback> callback = new JNISoundTriggerCallback(env, thiz, weak_this);
337
338 sound_trigger_module_handle_t handle =
339 (sound_trigger_module_handle_t)env->GetIntField(thiz, gModuleFields.mId);
340
341 sp<SoundTrigger> module = SoundTrigger::attach(handle, callback);
342 if (module == 0) {
343 return;
344 }
345
346 setSoundTrigger(env, thiz, module);
347}
348
349static void
350android_hardware_SoundTrigger_detach(JNIEnv *env, jobject thiz)
351{
352 ALOGV("detach");
353 sp<SoundTrigger> module = setSoundTrigger(env, thiz, 0);
354 ALOGV("detach module %p", module.get());
355 if (module != 0) {
356 ALOGV("detach module->detach()");
357 module->detach();
358 }
359}
360
361static void
362android_hardware_SoundTrigger_finalize(JNIEnv *env, jobject thiz)
363{
364 ALOGV("finalize");
365 sp<SoundTrigger> module = getSoundTrigger(env, thiz);
366 if (module != 0) {
367 ALOGW("SoundTrigger finalized without being detached");
368 }
369 android_hardware_SoundTrigger_detach(env, thiz);
370}
371
372static jint
373android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz,
374 jobject jSoundModel, jintArray jHandle)
375{
376 jint status = SOUNDTRIGGER_STATUS_OK;
377 char *nData = NULL;
378 struct sound_trigger_sound_model *nSoundModel;
379 jbyteArray jData;
380 sp<MemoryDealer> memoryDealer;
381 sp<IMemory> memory;
382 size_t size;
383 sound_model_handle_t handle;
384
385 ALOGV("loadSoundModel");
386 sp<SoundTrigger> module = getSoundTrigger(env, thiz);
387 if (module == NULL) {
388 return SOUNDTRIGGER_STATUS_ERROR;
389 }
390 if (jHandle == NULL) {
391 return SOUNDTRIGGER_STATUS_BAD_VALUE;
392 }
393 jsize jHandleLen = env->GetArrayLength(jHandle);
394 if (jHandleLen == 0) {
395 return SOUNDTRIGGER_STATUS_BAD_VALUE;
396 }
397 jint *nHandle = env->GetIntArrayElements(jHandle, NULL);
398 if (nHandle == NULL) {
399 return SOUNDTRIGGER_STATUS_ERROR;
400 }
401 if (!env->IsInstanceOf(jSoundModel, gSoundModelClass)) {
402 status = SOUNDTRIGGER_STATUS_BAD_VALUE;
403 goto exit;
404 }
405 size_t offset;
406 sound_trigger_sound_model_type_t type;
407 if (env->IsInstanceOf(jSoundModel, gKeyPhraseSoundModelClass)) {
408 offset = sizeof(struct sound_trigger_phrase_sound_model);
409 type = SOUND_MODEL_TYPE_KEYPHRASE;
410 } else {
411 offset = sizeof(struct sound_trigger_sound_model);
412 type = SOUND_MODEL_TYPE_UNKNOWN;
413 }
414 jData = (jbyteArray)env->GetObjectField(jSoundModel, gSoundModelFields.data);
415 if (jData == NULL) {
416 status = SOUNDTRIGGER_STATUS_BAD_VALUE;
417 goto exit;
418 }
419 size = env->GetArrayLength(jData);
420
421 nData = (char *)env->GetByteArrayElements(jData, NULL);
422 if (jData == NULL) {
423 status = SOUNDTRIGGER_STATUS_ERROR;
424 goto exit;
425 }
426
427 memoryDealer = new MemoryDealer(offset + size, "SoundTrigge-JNI::LoadModel");
428 if (memoryDealer == 0) {
429 status = SOUNDTRIGGER_STATUS_ERROR;
430 goto exit;
431 }
432 memory = memoryDealer->allocate(offset + size);
433 if (memory == 0 || memory->pointer() == NULL) {
434 status = SOUNDTRIGGER_STATUS_ERROR;
435 goto exit;
436 }
437
438 nSoundModel = (struct sound_trigger_sound_model *)memory->pointer();
439
440 nSoundModel->type = type;
441 nSoundModel->data_size = size;
442 nSoundModel->data_offset = offset;
443 memcpy((char *)nSoundModel + offset, nData, size);
444 if (type == SOUND_MODEL_TYPE_KEYPHRASE) {
445 struct sound_trigger_phrase_sound_model *phraseModel =
446 (struct sound_trigger_phrase_sound_model *)nSoundModel;
447
448 jobjectArray jPhrases =
449 (jobjectArray)env->GetObjectField(jSoundModel, gKeyPhraseSoundModelFields.keyPhrases);
450 if (jPhrases == NULL) {
451 status = SOUNDTRIGGER_STATUS_BAD_VALUE;
452 goto exit;
453 }
454
455 size_t numPhrases = env->GetArrayLength(jPhrases);
456 phraseModel->num_phrases = numPhrases;
457 ALOGV("loadSoundModel numPhrases %d", numPhrases);
458 for (size_t i = 0; i < numPhrases; i++) {
459 jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
460 phraseModel->phrases[i].recognition_mode =
461 env->GetIntField(jPhrase,gKeyPhraseFields.recognitionModes);
462 phraseModel->phrases[i].num_users =
463 env->GetIntField(jPhrase, gKeyPhraseFields.numUsers);
464 jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyPhraseFields.locale);
465 const char *nLocale = env->GetStringUTFChars(jLocale, NULL);
466 strncpy(phraseModel->phrases[i].locale,
467 nLocale,
468 SOUND_TRIGGER_MAX_LOCALE_LEN);
469 jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyPhraseFields.text);
470 const char *nText = env->GetStringUTFChars(jText, NULL);
471 strncpy(phraseModel->phrases[i].text,
472 nText,
473 SOUND_TRIGGER_MAX_STRING_LEN);
474
475 env->ReleaseStringUTFChars(jLocale, nLocale);
476 env->DeleteLocalRef(jLocale);
477 env->ReleaseStringUTFChars(jText, nText);
478 env->DeleteLocalRef(jText);
479 ALOGV("loadSoundModel phrases %d text %s locale %s",
480 i, phraseModel->phrases[i].text, phraseModel->phrases[i].locale);
481 }
482 env->DeleteLocalRef(jPhrases);
483 }
484 status = module->loadSoundModel(memory, &handle);
485 ALOGV("loadSoundModel status %d handle %d", status, handle);
486
487exit:
488 if (nHandle != NULL) {
489 nHandle[0] = (jint)handle;
490 env->ReleaseIntArrayElements(jHandle, nHandle, NULL);
491 }
492 if (nData != NULL) {
493 env->ReleaseByteArrayElements(jData, (jbyte *)nData, NULL);
494 }
495 return status;
496}
497
498static jint
499android_hardware_SoundTrigger_unloadSoundModel(JNIEnv *env, jobject thiz,
500 jint jHandle)
501{
502 jint status = SOUNDTRIGGER_STATUS_OK;
503 ALOGV("unloadSoundModel");
504 sp<SoundTrigger> module = getSoundTrigger(env, thiz);
505 if (module == NULL) {
506 return SOUNDTRIGGER_STATUS_ERROR;
507 }
508 status = module->unloadSoundModel((sound_model_handle_t)jHandle);
509
510 return status;
511}
512
513static jint
514android_hardware_SoundTrigger_startRecognition(JNIEnv *env, jobject thiz,
515 jint jHandle, jbyteArray jData)
516{
517 jint status = SOUNDTRIGGER_STATUS_OK;
518 ALOGV("startRecognition");
519 sp<SoundTrigger> module = getSoundTrigger(env, thiz);
520 if (module == NULL) {
521 return SOUNDTRIGGER_STATUS_ERROR;
522 }
523 jsize dataSize = 0;
524 char *nData = NULL;
525 sp<IMemory> memory;
526 if (jData != NULL) {
527 dataSize = env->GetArrayLength(jData);
528 if (dataSize == 0) {
529 return SOUNDTRIGGER_STATUS_BAD_VALUE;
530 }
531 nData = (char *)env->GetByteArrayElements(jData, NULL);
532 if (nData == NULL) {
533 return SOUNDTRIGGER_STATUS_ERROR;
534 }
535 sp<MemoryDealer> memoryDealer =
536 new MemoryDealer(dataSize, "SoundTrigge-JNI::StartRecognition");
537 if (memoryDealer == 0) {
538 return SOUNDTRIGGER_STATUS_ERROR;
539 }
540 memory = memoryDealer->allocate(dataSize);
541 if (memory == 0 || memory->pointer() == NULL) {
542 return SOUNDTRIGGER_STATUS_ERROR;
543 }
544 memcpy(memory->pointer(), nData, dataSize);
545 }
546
547 status = module->startRecognition(jHandle, memory);
548 return status;
549}
550
551static jint
552android_hardware_SoundTrigger_stopRecognition(JNIEnv *env, jobject thiz,
553 jint jHandle)
554{
555 jint status = SOUNDTRIGGER_STATUS_OK;
556 ALOGV("stopRecognition");
557 sp<SoundTrigger> module = getSoundTrigger(env, thiz);
558 if (module == NULL) {
559 return SOUNDTRIGGER_STATUS_ERROR;
560 }
561 status = module->stopRecognition(jHandle);
562 return status;
563}
564
565static JNINativeMethod gMethods[] = {
566 {"listModules",
567 "(Ljava/util/ArrayList;)I",
568 (void *)android_hardware_SoundTrigger_listModules},
569};
570
571
572static JNINativeMethod gModuleMethods[] = {
573 {"native_setup",
574 "(Ljava/lang/Object;)V",
575 (void *)android_hardware_SoundTrigger_setup},
576 {"native_finalize",
577 "()V",
578 (void *)android_hardware_SoundTrigger_finalize},
579 {"detach",
580 "()V",
581 (void *)android_hardware_SoundTrigger_detach},
582 {"loadSoundModel",
583 "(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;[I)I",
584 (void *)android_hardware_SoundTrigger_loadSoundModel},
585 {"unloadSoundModel",
586 "(I)I",
587 (void *)android_hardware_SoundTrigger_unloadSoundModel},
588 {"startRecognition",
589 "(I[B)I",
590 (void *)android_hardware_SoundTrigger_startRecognition},
591 {"stopRecognition",
592 "(I)I",
593 (void *)android_hardware_SoundTrigger_stopRecognition},
594};
595
596int register_android_hardware_SoundTrigger(JNIEnv *env)
597{
598 jclass arrayListClass = env->FindClass("java/util/ArrayList");
599 gArrayListClass = (jclass) env->NewGlobalRef(arrayListClass);
600 gArrayListMethods.add = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
601
602 jclass lClass = env->FindClass(kSoundTriggerClassPathName);
603 gSoundTriggerClass = (jclass) env->NewGlobalRef(lClass);
604
605 jclass moduleClass = env->FindClass(kModuleClassPathName);
606 gModuleClass = (jclass) env->NewGlobalRef(moduleClass);
607 gPostEventFromNative = env->GetStaticMethodID(moduleClass, "postEventFromNative",
608 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
609 gModuleFields.mNativeContext = env->GetFieldID(moduleClass, "mNativeContext", "J");
610 gModuleFields.mId = env->GetFieldID(moduleClass, "mId", "I");
611
612
613 jclass modulePropertiesClass = env->FindClass(kModulePropertiesClassPathName);
614 gModulePropertiesClass = (jclass) env->NewGlobalRef(modulePropertiesClass);
615 gModulePropertiesCstor = env->GetMethodID(modulePropertiesClass, "<init>",
616 "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZI)V");
617
618 jclass soundModelClass = env->FindClass(kSoundModelClassPathName);
619 gSoundModelClass = (jclass) env->NewGlobalRef(soundModelClass);
620 gSoundModelFields.data = env->GetFieldID(soundModelClass, "data", "[B");
621
622 jclass keyPhraseClass = env->FindClass(kKeyPhraseClassPathName);
623 gKeyPhraseClass = (jclass) env->NewGlobalRef(keyPhraseClass);
624 gKeyPhraseFields.recognitionModes = env->GetFieldID(keyPhraseClass, "recognitionModes", "I");
625 gKeyPhraseFields.locale = env->GetFieldID(keyPhraseClass, "locale", "Ljava/lang/String;");
626 gKeyPhraseFields.text = env->GetFieldID(keyPhraseClass, "text", "Ljava/lang/String;");
627 gKeyPhraseFields.numUsers = env->GetFieldID(keyPhraseClass, "numUsers", "I");
628
629 jclass keyPhraseSoundModelClass = env->FindClass(kKeyPhraseSoundModelClassPathName);
630 gKeyPhraseSoundModelClass = (jclass) env->NewGlobalRef(keyPhraseSoundModelClass);
631 gKeyPhraseSoundModelFields.keyPhrases = env->GetFieldID(keyPhraseSoundModelClass,
632 "keyPhrases",
633 "[Landroid/hardware/soundtrigger/SoundTrigger$KeyPhrase;");
634
635
636 jclass recognitionEventClass = env->FindClass(kRecognitionEventClassPathName);
637 gRecognitionEventClass = (jclass) env->NewGlobalRef(recognitionEventClass);
638 gRecognitionEventCstor = env->GetMethodID(recognitionEventClass, "<init>",
639 "(IIZII[B)V");
640
641 jclass keyPhraseRecognitionEventClass = env->FindClass(kKeyPhraseRecognitionEventClassPathName);
642 gKeyPhraseRecognitionEventClass = (jclass) env->NewGlobalRef(keyPhraseRecognitionEventClass);
643 gKeyPhraseRecognitionEventCstor = env->GetMethodID(keyPhraseRecognitionEventClass, "<init>",
644 "(IIZII[BZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionExtra;)V");
645
646
647 jclass keyPhraseRecognitionExtraClass = env->FindClass(kKeyPhraseRecognitionExtraClassPathName);
648 gKeyPhraseRecognitionExtraClass = (jclass) env->NewGlobalRef(keyPhraseRecognitionExtraClass);
649 gKeyPhraseRecognitionExtraCstor = env->GetMethodID(keyPhraseRecognitionExtraClass, "<init>",
650 "([II)V");
651
652 int status = AndroidRuntime::registerNativeMethods(env,
653 kSoundTriggerClassPathName, gMethods, NELEM(gMethods));
654
655 if (status == 0) {
656 status = AndroidRuntime::registerNativeMethods(env,
657 kModuleClassPathName, gModuleMethods, NELEM(gModuleMethods));
658 }
659
660 return status;
661}