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