Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 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" |
Steven Moreland | 2279b25 | 2017-07-19 09:50:45 -0700 | [diff] [blame] | 23 | #include <nativehelper/JNIHelp.h> |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 24 | #include <nativehelper/ScopedUtfChars.h> |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 25 | #include "core_jni_helpers.h" |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 26 | #include <system/sound_trigger.h> |
| 27 | #include <soundtrigger/SoundTriggerCallback.h> |
| 28 | #include <soundtrigger/SoundTrigger.h> |
| 29 | #include <utils/RefBase.h> |
| 30 | #include <utils/Vector.h> |
| 31 | #include <binder/IMemory.h> |
| 32 | #include <binder/MemoryDealer.h> |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 33 | #include "android_media_AudioFormat.h" |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 34 | |
| 35 | using namespace android; |
| 36 | |
| 37 | static jclass gArrayListClass; |
| 38 | static struct { |
| 39 | jmethodID add; |
| 40 | } gArrayListMethods; |
| 41 | |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 42 | static jclass gUUIDClass; |
| 43 | static struct { |
| 44 | jmethodID toString; |
| 45 | } gUUIDMethods; |
| 46 | |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 47 | static const char* const kSoundTriggerClassPathName = "android/hardware/soundtrigger/SoundTrigger"; |
| 48 | static jclass gSoundTriggerClass; |
| 49 | |
| 50 | static const char* const kModuleClassPathName = "android/hardware/soundtrigger/SoundTriggerModule"; |
| 51 | static jclass gModuleClass; |
| 52 | static struct { |
| 53 | jfieldID mNativeContext; |
| 54 | jfieldID mId; |
| 55 | } gModuleFields; |
| 56 | static jmethodID gPostEventFromNative; |
| 57 | |
| 58 | static const char* const kModulePropertiesClassPathName = |
| 59 | "android/hardware/soundtrigger/SoundTrigger$ModuleProperties"; |
| 60 | static jclass gModulePropertiesClass; |
| 61 | static jmethodID gModulePropertiesCstor; |
| 62 | |
| 63 | static const char* const kSoundModelClassPathName = |
| 64 | "android/hardware/soundtrigger/SoundTrigger$SoundModel"; |
| 65 | static jclass gSoundModelClass; |
| 66 | static struct { |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 67 | jfieldID uuid; |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 68 | jfieldID vendorUuid; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 69 | jfieldID data; |
| 70 | } gSoundModelFields; |
| 71 | |
Ryan Bavetta | ee3fc89 | 2016-01-26 20:49:28 -0800 | [diff] [blame] | 72 | static const char* const kGenericSoundModelClassPathName = |
| 73 | "android/hardware/soundtrigger/SoundTrigger$GenericSoundModel"; |
| 74 | static jclass gGenericSoundModelClass; |
| 75 | |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 76 | static const char* const kKeyphraseClassPathName = |
| 77 | "android/hardware/soundtrigger/SoundTrigger$Keyphrase"; |
| 78 | static jclass gKeyphraseClass; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 79 | static struct { |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 80 | jfieldID id; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 81 | jfieldID recognitionModes; |
| 82 | jfieldID locale; |
| 83 | jfieldID text; |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 84 | jfieldID users; |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 85 | } gKeyphraseFields; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 86 | |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 87 | static const char* const kKeyphraseSoundModelClassPathName = |
| 88 | "android/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel"; |
| 89 | static jclass gKeyphraseSoundModelClass; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 90 | static struct { |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 91 | jfieldID keyphrases; |
| 92 | } gKeyphraseSoundModelFields; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 93 | |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 94 | static const char* const kRecognitionConfigClassPathName = |
| 95 | "android/hardware/soundtrigger/SoundTrigger$RecognitionConfig"; |
| 96 | static jclass gRecognitionConfigClass; |
| 97 | static struct { |
| 98 | jfieldID captureRequested; |
| 99 | jfieldID keyphrases; |
| 100 | jfieldID data; |
| 101 | } gRecognitionConfigFields; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 102 | |
| 103 | static const char* const kRecognitionEventClassPathName = |
| 104 | "android/hardware/soundtrigger/SoundTrigger$RecognitionEvent"; |
| 105 | static jclass gRecognitionEventClass; |
| 106 | static jmethodID gRecognitionEventCstor; |
| 107 | |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 108 | static const char* const kKeyphraseRecognitionEventClassPathName = |
| 109 | "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent"; |
| 110 | static jclass gKeyphraseRecognitionEventClass; |
| 111 | static jmethodID gKeyphraseRecognitionEventCstor; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 112 | |
Ryan Bavetta | ee3fc89 | 2016-01-26 20:49:28 -0800 | [diff] [blame] | 113 | static const char* const kGenericRecognitionEventClassPathName = |
| 114 | "android/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent"; |
| 115 | static jclass gGenericRecognitionEventClass; |
| 116 | static jmethodID gGenericRecognitionEventCstor; |
| 117 | |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 118 | static const char* const kKeyphraseRecognitionExtraClassPathName = |
| 119 | "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra"; |
| 120 | static jclass gKeyphraseRecognitionExtraClass; |
| 121 | static jmethodID gKeyphraseRecognitionExtraCstor; |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 122 | static struct { |
| 123 | jfieldID id; |
| 124 | jfieldID recognitionModes; |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 125 | jfieldID coarseConfidenceLevel; |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 126 | jfieldID confidenceLevels; |
| 127 | } gKeyphraseRecognitionExtraFields; |
| 128 | |
| 129 | static const char* const kConfidenceLevelClassPathName = |
| 130 | "android/hardware/soundtrigger/SoundTrigger$ConfidenceLevel"; |
| 131 | static jclass gConfidenceLevelClass; |
| 132 | static jmethodID gConfidenceLevelCstor; |
| 133 | static struct { |
| 134 | jfieldID userId; |
| 135 | jfieldID confidenceLevel; |
| 136 | } gConfidenceLevelFields; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 137 | |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 138 | static const char* const kAudioFormatClassPathName = |
| 139 | "android/media/AudioFormat"; |
| 140 | static jclass gAudioFormatClass; |
| 141 | static jmethodID gAudioFormatCstor; |
| 142 | |
| 143 | static const char* const kSoundModelEventClassPathName = |
| 144 | "android/hardware/soundtrigger/SoundTrigger$SoundModelEvent"; |
| 145 | static jclass gSoundModelEventClass; |
| 146 | static jmethodID gSoundModelEventCstor; |
| 147 | |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 148 | static Mutex gLock; |
| 149 | |
| 150 | enum { |
| 151 | SOUNDTRIGGER_STATUS_OK = 0, |
| 152 | SOUNDTRIGGER_STATUS_ERROR = INT_MIN, |
| 153 | SOUNDTRIGGER_PERMISSION_DENIED = -1, |
| 154 | SOUNDTRIGGER_STATUS_NO_INIT = -19, |
| 155 | SOUNDTRIGGER_STATUS_BAD_VALUE = -22, |
| 156 | SOUNDTRIGGER_STATUS_DEAD_OBJECT = -32, |
| 157 | SOUNDTRIGGER_INVALID_OPERATION = -38, |
| 158 | }; |
| 159 | |
| 160 | enum { |
| 161 | SOUNDTRIGGER_EVENT_RECOGNITION = 1, |
| 162 | SOUNDTRIGGER_EVENT_SERVICE_DIED = 2, |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 163 | SOUNDTRIGGER_EVENT_SOUNDMODEL = 3, |
| 164 | SOUNDTRIGGER_EVENT_SERVICE_STATE_CHANGE = 4, |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 165 | }; |
| 166 | |
| 167 | // ---------------------------------------------------------------------------- |
| 168 | // ref-counted object for callbacks |
| 169 | class JNISoundTriggerCallback: public SoundTriggerCallback |
| 170 | { |
| 171 | public: |
| 172 | JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz); |
| 173 | ~JNISoundTriggerCallback(); |
| 174 | |
| 175 | virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event); |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 176 | virtual void onSoundModelEvent(struct sound_trigger_model_event *event); |
| 177 | virtual void onServiceStateChange(sound_trigger_service_state_t state); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 178 | virtual void onServiceDied(); |
| 179 | |
| 180 | private: |
| 181 | jclass mClass; // Reference to SoundTrigger class |
| 182 | jobject mObject; // Weak ref to SoundTrigger Java object to call on |
| 183 | }; |
| 184 | |
| 185 | JNISoundTriggerCallback::JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz) |
| 186 | { |
| 187 | |
| 188 | // Hold onto the SoundTriggerModule class for use in calling the static method |
| 189 | // that posts events to the application thread. |
| 190 | jclass clazz = env->GetObjectClass(thiz); |
| 191 | if (clazz == NULL) { |
| 192 | ALOGE("Can't find class %s", kModuleClassPathName); |
| 193 | return; |
| 194 | } |
| 195 | mClass = (jclass)env->NewGlobalRef(clazz); |
| 196 | |
| 197 | // We use a weak reference so the SoundTriggerModule object can be garbage collected. |
| 198 | // The reference is only used as a proxy for callbacks. |
| 199 | mObject = env->NewGlobalRef(weak_thiz); |
| 200 | } |
| 201 | |
| 202 | JNISoundTriggerCallback::~JNISoundTriggerCallback() |
| 203 | { |
| 204 | // remove global references |
| 205 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 206 | env->DeleteGlobalRef(mObject); |
| 207 | env->DeleteGlobalRef(mClass); |
| 208 | } |
| 209 | |
| 210 | void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognition_event *event) |
| 211 | { |
| 212 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 213 | jobject jEvent = NULL; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 214 | jbyteArray jData = NULL; |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 215 | |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 216 | if (event->data_size) { |
| 217 | jData = env->NewByteArray(event->data_size); |
| 218 | jbyte *nData = env->GetByteArrayElements(jData, NULL); |
| 219 | memcpy(nData, (char *)event + event->data_offset, event->data_size); |
| 220 | env->ReleaseByteArrayElements(jData, nData, 0); |
| 221 | } |
| 222 | |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 223 | jobject jAudioFormat = NULL; |
Eric Laurent | 39fcca0 | 2014-09-05 16:44:19 -0700 | [diff] [blame] | 224 | if (event->trigger_in_data || event->capture_available) { |
Eric Laurent | 66ef06a | 2019-02-26 18:23:22 -0800 | [diff] [blame] | 225 | jint channelMask = (jint)audio_channel_mask_get_bits(event->audio_config.channel_mask); |
| 226 | jint channelIndexMask = (jint)AUDIO_CHANNEL_NONE; |
| 227 | |
| 228 | switch (audio_channel_mask_get_representation(event->audio_config.channel_mask)) { |
| 229 | case AUDIO_CHANNEL_REPRESENTATION_INDEX: |
| 230 | channelIndexMask = channelMask; |
| 231 | channelMask = (jint)AUDIO_CHANNEL_NONE; |
| 232 | break; |
| 233 | default: |
| 234 | break; |
| 235 | } |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 236 | jAudioFormat = env->NewObject(gAudioFormatClass, |
| 237 | gAudioFormatCstor, |
| 238 | audioFormatFromNative(event->audio_config.format), |
| 239 | event->audio_config.sample_rate, |
Eric Laurent | 66ef06a | 2019-02-26 18:23:22 -0800 | [diff] [blame] | 240 | channelMask, |
| 241 | channelIndexMask); |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 242 | |
| 243 | } |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 244 | if (event->type == SOUND_MODEL_TYPE_KEYPHRASE) { |
| 245 | struct sound_trigger_phrase_recognition_event *phraseEvent = |
| 246 | (struct sound_trigger_phrase_recognition_event *)event; |
| 247 | |
| 248 | jobjectArray jExtras = env->NewObjectArray(phraseEvent->num_phrases, |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 249 | gKeyphraseRecognitionExtraClass, NULL); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 250 | if (jExtras == NULL) { |
| 251 | return; |
| 252 | } |
| 253 | |
| 254 | for (size_t i = 0; i < phraseEvent->num_phrases; i++) { |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 255 | jobjectArray jConfidenceLevels = env->NewObjectArray( |
| 256 | phraseEvent->phrase_extras[i].num_levels, |
| 257 | gConfidenceLevelClass, NULL); |
| 258 | |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 259 | if (jConfidenceLevels == NULL) { |
| 260 | return; |
| 261 | } |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 262 | for (size_t j = 0; j < phraseEvent->phrase_extras[i].num_levels; j++) { |
| 263 | jobject jConfidenceLevel = env->NewObject(gConfidenceLevelClass, |
| 264 | gConfidenceLevelCstor, |
| 265 | phraseEvent->phrase_extras[i].levels[j].user_id, |
| 266 | phraseEvent->phrase_extras[i].levels[j].level); |
| 267 | env->SetObjectArrayElement(jConfidenceLevels, j, jConfidenceLevel); |
| 268 | env->DeleteLocalRef(jConfidenceLevel); |
| 269 | } |
| 270 | |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 271 | jobject jNewExtra = env->NewObject(gKeyphraseRecognitionExtraClass, |
| 272 | gKeyphraseRecognitionExtraCstor, |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 273 | phraseEvent->phrase_extras[i].id, |
| 274 | phraseEvent->phrase_extras[i].recognition_modes, |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 275 | phraseEvent->phrase_extras[i].confidence_level, |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 276 | jConfidenceLevels); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 277 | |
| 278 | if (jNewExtra == NULL) { |
| 279 | return; |
| 280 | } |
| 281 | env->SetObjectArrayElement(jExtras, i, jNewExtra); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 282 | env->DeleteLocalRef(jNewExtra); |
| 283 | env->DeleteLocalRef(jConfidenceLevels); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 284 | } |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 285 | jEvent = env->NewObject(gKeyphraseRecognitionEventClass, gKeyphraseRecognitionEventCstor, |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 286 | event->status, event->model, event->capture_available, |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 287 | event->capture_session, event->capture_delay_ms, |
| 288 | event->capture_preamble_ms, event->trigger_in_data, |
| 289 | jAudioFormat, jData, jExtras); |
Eric Laurent | 8f89feb | 2014-10-29 15:52:43 -0700 | [diff] [blame] | 290 | env->DeleteLocalRef(jExtras); |
Ryan Bavetta | ee3fc89 | 2016-01-26 20:49:28 -0800 | [diff] [blame] | 291 | } else if (event->type == SOUND_MODEL_TYPE_GENERIC) { |
| 292 | jEvent = env->NewObject(gGenericRecognitionEventClass, gGenericRecognitionEventCstor, |
| 293 | event->status, event->model, event->capture_available, |
| 294 | event->capture_session, event->capture_delay_ms, |
| 295 | event->capture_preamble_ms, event->trigger_in_data, |
| 296 | jAudioFormat, jData); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 297 | } else { |
| 298 | jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor, |
| 299 | event->status, event->model, event->capture_available, |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 300 | event->capture_session, event->capture_delay_ms, |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 301 | event->capture_preamble_ms, event->trigger_in_data, |
| 302 | jAudioFormat, jData); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 303 | } |
| 304 | |
Eric Laurent | 8f89feb | 2014-10-29 15:52:43 -0700 | [diff] [blame] | 305 | if (jAudioFormat != NULL) { |
| 306 | env->DeleteLocalRef(jAudioFormat); |
| 307 | } |
| 308 | if (jData != NULL) { |
| 309 | env->DeleteLocalRef(jData); |
| 310 | } |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 311 | |
| 312 | env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject, |
| 313 | SOUNDTRIGGER_EVENT_RECOGNITION, 0, 0, jEvent); |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 314 | |
| 315 | env->DeleteLocalRef(jEvent); |
| 316 | if (env->ExceptionCheck()) { |
| 317 | ALOGW("An exception occurred while notifying an event."); |
| 318 | env->ExceptionClear(); |
| 319 | } |
| 320 | } |
| 321 | |
| 322 | void JNISoundTriggerCallback::onSoundModelEvent(struct sound_trigger_model_event *event) |
| 323 | { |
| 324 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 325 | jobject jEvent = NULL; |
| 326 | jbyteArray jData = NULL; |
| 327 | |
| 328 | if (event->data_size) { |
| 329 | jData = env->NewByteArray(event->data_size); |
| 330 | jbyte *nData = env->GetByteArrayElements(jData, NULL); |
| 331 | memcpy(nData, (char *)event + event->data_offset, event->data_size); |
| 332 | env->ReleaseByteArrayElements(jData, nData, 0); |
| 333 | } |
| 334 | |
| 335 | jEvent = env->NewObject(gSoundModelEventClass, gSoundModelEventCstor, |
| 336 | event->status, event->model, jData); |
| 337 | |
| 338 | env->DeleteLocalRef(jData); |
| 339 | env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject, |
| 340 | SOUNDTRIGGER_EVENT_SOUNDMODEL, 0, 0, jEvent); |
| 341 | env->DeleteLocalRef(jEvent); |
| 342 | if (env->ExceptionCheck()) { |
| 343 | ALOGW("An exception occurred while notifying an event."); |
| 344 | env->ExceptionClear(); |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | void JNISoundTriggerCallback::onServiceStateChange(sound_trigger_service_state_t state) |
| 349 | { |
| 350 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 351 | env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject, |
| 352 | SOUNDTRIGGER_EVENT_SERVICE_STATE_CHANGE, state, 0, NULL); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 353 | if (env->ExceptionCheck()) { |
| 354 | ALOGW("An exception occurred while notifying an event."); |
| 355 | env->ExceptionClear(); |
| 356 | } |
| 357 | } |
| 358 | |
| 359 | void JNISoundTriggerCallback::onServiceDied() |
| 360 | { |
| 361 | JNIEnv *env = AndroidRuntime::getJNIEnv(); |
| 362 | |
| 363 | env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject, |
| 364 | SOUNDTRIGGER_EVENT_SERVICE_DIED, 0, 0, NULL); |
| 365 | if (env->ExceptionCheck()) { |
| 366 | ALOGW("An exception occurred while notifying an event."); |
| 367 | env->ExceptionClear(); |
| 368 | } |
| 369 | } |
| 370 | |
| 371 | // ---------------------------------------------------------------------------- |
| 372 | |
| 373 | static sp<SoundTrigger> getSoundTrigger(JNIEnv* env, jobject thiz) |
| 374 | { |
| 375 | Mutex::Autolock l(gLock); |
| 376 | SoundTrigger* const st = (SoundTrigger*)env->GetLongField(thiz, |
| 377 | gModuleFields.mNativeContext); |
| 378 | return sp<SoundTrigger>(st); |
| 379 | } |
| 380 | |
| 381 | static sp<SoundTrigger> setSoundTrigger(JNIEnv* env, jobject thiz, const sp<SoundTrigger>& module) |
| 382 | { |
| 383 | Mutex::Autolock l(gLock); |
| 384 | sp<SoundTrigger> old = (SoundTrigger*)env->GetLongField(thiz, |
| 385 | gModuleFields.mNativeContext); |
| 386 | if (module.get()) { |
| 387 | module->incStrong((void*)setSoundTrigger); |
| 388 | } |
| 389 | if (old != 0) { |
| 390 | old->decStrong((void*)setSoundTrigger); |
| 391 | } |
| 392 | env->SetLongField(thiz, gModuleFields.mNativeContext, (jlong)module.get()); |
| 393 | return old; |
| 394 | } |
| 395 | |
| 396 | |
| 397 | static jint |
| 398 | android_hardware_SoundTrigger_listModules(JNIEnv *env, jobject clazz, |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 399 | jstring opPackageName, jobject jModules) |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 400 | { |
| 401 | ALOGV("listModules"); |
| 402 | |
| 403 | if (jModules == NULL) { |
| 404 | ALOGE("listModules NULL AudioPatch ArrayList"); |
| 405 | return SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 406 | } |
| 407 | if (!env->IsInstanceOf(jModules, gArrayListClass)) { |
| 408 | ALOGE("listModules not an arraylist"); |
| 409 | return SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 410 | } |
| 411 | |
| 412 | unsigned int numModules = 0; |
| 413 | struct sound_trigger_module_descriptor *nModules = NULL; |
| 414 | |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 415 | ScopedUtfChars opPackageNameStr(env, opPackageName); |
| 416 | const String16 opPackageNameString16 = String16(opPackageNameStr.c_str()); |
| 417 | |
| 418 | status_t status = SoundTrigger::listModules(opPackageNameString16, nModules, &numModules); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 419 | if (status != NO_ERROR || numModules == 0) { |
| 420 | return (jint)status; |
| 421 | } |
| 422 | |
| 423 | nModules = (struct sound_trigger_module_descriptor *) |
| 424 | calloc(numModules, sizeof(struct sound_trigger_module_descriptor)); |
| 425 | |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 426 | status = SoundTrigger::listModules(opPackageNameString16, nModules, &numModules); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 427 | ALOGV("listModules SoundTrigger::listModules status %d numModules %d", status, numModules); |
| 428 | |
| 429 | if (status != NO_ERROR) { |
| 430 | numModules = 0; |
| 431 | } |
| 432 | |
| 433 | for (size_t i = 0; i < numModules; i++) { |
| 434 | char str[SOUND_TRIGGER_MAX_STRING_LEN]; |
| 435 | |
| 436 | jstring implementor = env->NewStringUTF(nModules[i].properties.implementor); |
| 437 | jstring description = env->NewStringUTF(nModules[i].properties.description); |
| 438 | SoundTrigger::guidToString(&nModules[i].properties.uuid, |
| 439 | str, |
| 440 | SOUND_TRIGGER_MAX_STRING_LEN); |
| 441 | jstring uuid = env->NewStringUTF(str); |
| 442 | |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 443 | ALOGV("listModules module %zu id %d description %s maxSoundModels %d", |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 444 | i, nModules[i].handle, nModules[i].properties.description, |
| 445 | nModules[i].properties.max_sound_models); |
| 446 | |
| 447 | jobject newModuleDesc = env->NewObject(gModulePropertiesClass, gModulePropertiesCstor, |
| 448 | nModules[i].handle, |
| 449 | implementor, description, uuid, |
| 450 | nModules[i].properties.version, |
| 451 | nModules[i].properties.max_sound_models, |
| 452 | nModules[i].properties.max_key_phrases, |
| 453 | nModules[i].properties.max_users, |
| 454 | nModules[i].properties.recognition_modes, |
| 455 | nModules[i].properties.capture_transition, |
| 456 | nModules[i].properties.max_buffer_ms, |
| 457 | nModules[i].properties.concurrent_capture, |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 458 | nModules[i].properties.power_consumption_mw, |
| 459 | nModules[i].properties.trigger_in_event); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 460 | |
| 461 | env->DeleteLocalRef(implementor); |
| 462 | env->DeleteLocalRef(description); |
| 463 | env->DeleteLocalRef(uuid); |
| 464 | if (newModuleDesc == NULL) { |
| 465 | status = SOUNDTRIGGER_STATUS_ERROR; |
| 466 | goto exit; |
| 467 | } |
| 468 | env->CallBooleanMethod(jModules, gArrayListMethods.add, newModuleDesc); |
| 469 | } |
| 470 | |
| 471 | exit: |
| 472 | free(nModules); |
| 473 | return (jint) status; |
| 474 | } |
| 475 | |
| 476 | static void |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 477 | android_hardware_SoundTrigger_setup(JNIEnv *env, jobject thiz, |
| 478 | jstring opPackageName, jobject weak_this) |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 479 | { |
| 480 | ALOGV("setup"); |
| 481 | |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 482 | ScopedUtfChars opPackageNameStr(env, opPackageName); |
| 483 | const String16 opPackageNameString16 = String16(opPackageNameStr.c_str()); |
| 484 | |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 485 | sp<JNISoundTriggerCallback> callback = new JNISoundTriggerCallback(env, thiz, weak_this); |
| 486 | |
| 487 | sound_trigger_module_handle_t handle = |
| 488 | (sound_trigger_module_handle_t)env->GetIntField(thiz, gModuleFields.mId); |
| 489 | |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 490 | sp<SoundTrigger> module = SoundTrigger::attach(opPackageNameString16, handle, callback); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 491 | if (module == 0) { |
| 492 | return; |
| 493 | } |
| 494 | |
| 495 | setSoundTrigger(env, thiz, module); |
| 496 | } |
| 497 | |
| 498 | static void |
| 499 | android_hardware_SoundTrigger_detach(JNIEnv *env, jobject thiz) |
| 500 | { |
| 501 | ALOGV("detach"); |
| 502 | sp<SoundTrigger> module = setSoundTrigger(env, thiz, 0); |
| 503 | ALOGV("detach module %p", module.get()); |
| 504 | if (module != 0) { |
| 505 | ALOGV("detach module->detach()"); |
| 506 | module->detach(); |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | static void |
| 511 | android_hardware_SoundTrigger_finalize(JNIEnv *env, jobject thiz) |
| 512 | { |
| 513 | ALOGV("finalize"); |
| 514 | sp<SoundTrigger> module = getSoundTrigger(env, thiz); |
| 515 | if (module != 0) { |
| 516 | ALOGW("SoundTrigger finalized without being detached"); |
| 517 | } |
| 518 | android_hardware_SoundTrigger_detach(env, thiz); |
| 519 | } |
| 520 | |
| 521 | static jint |
| 522 | android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz, |
| 523 | jobject jSoundModel, jintArray jHandle) |
| 524 | { |
| 525 | jint status = SOUNDTRIGGER_STATUS_OK; |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 526 | jbyte *nData = NULL; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 527 | struct sound_trigger_sound_model *nSoundModel; |
| 528 | jbyteArray jData; |
| 529 | sp<MemoryDealer> memoryDealer; |
| 530 | sp<IMemory> memory; |
| 531 | size_t size; |
George Burgess IV | 2df0c67 | 2017-01-24 15:48:28 -0800 | [diff] [blame] | 532 | sound_model_handle_t handle = 0; |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 533 | jobject jUuid; |
| 534 | jstring jUuidString; |
| 535 | const char *nUuidString; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 536 | |
| 537 | ALOGV("loadSoundModel"); |
| 538 | sp<SoundTrigger> module = getSoundTrigger(env, thiz); |
| 539 | if (module == NULL) { |
| 540 | return SOUNDTRIGGER_STATUS_ERROR; |
| 541 | } |
| 542 | if (jHandle == NULL) { |
| 543 | return SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 544 | } |
| 545 | jsize jHandleLen = env->GetArrayLength(jHandle); |
| 546 | if (jHandleLen == 0) { |
| 547 | return SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 548 | } |
| 549 | jint *nHandle = env->GetIntArrayElements(jHandle, NULL); |
| 550 | if (nHandle == NULL) { |
| 551 | return SOUNDTRIGGER_STATUS_ERROR; |
| 552 | } |
| 553 | if (!env->IsInstanceOf(jSoundModel, gSoundModelClass)) { |
| 554 | status = SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 555 | goto exit; |
| 556 | } |
| 557 | size_t offset; |
| 558 | sound_trigger_sound_model_type_t type; |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 559 | if (env->IsInstanceOf(jSoundModel, gKeyphraseSoundModelClass)) { |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 560 | offset = sizeof(struct sound_trigger_phrase_sound_model); |
| 561 | type = SOUND_MODEL_TYPE_KEYPHRASE; |
Ryan Bavetta | ee3fc89 | 2016-01-26 20:49:28 -0800 | [diff] [blame] | 562 | } else if (env->IsInstanceOf(jSoundModel, gGenericSoundModelClass)) { |
| 563 | offset = sizeof(struct sound_trigger_generic_sound_model); |
| 564 | type = SOUND_MODEL_TYPE_GENERIC; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 565 | } else { |
| 566 | offset = sizeof(struct sound_trigger_sound_model); |
| 567 | type = SOUND_MODEL_TYPE_UNKNOWN; |
| 568 | } |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 569 | |
| 570 | jUuid = env->GetObjectField(jSoundModel, gSoundModelFields.uuid); |
| 571 | jUuidString = (jstring)env->CallObjectMethod(jUuid, gUUIDMethods.toString); |
| 572 | nUuidString = env->GetStringUTFChars(jUuidString, NULL); |
| 573 | sound_trigger_uuid_t nUuid; |
| 574 | SoundTrigger::stringToGuid(nUuidString, &nUuid); |
| 575 | env->ReleaseStringUTFChars(jUuidString, nUuidString); |
| 576 | env->DeleteLocalRef(jUuidString); |
| 577 | |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 578 | sound_trigger_uuid_t nVendorUuid; |
| 579 | jUuid = env->GetObjectField(jSoundModel, gSoundModelFields.vendorUuid); |
| 580 | if (jUuid != NULL) { |
| 581 | jUuidString = (jstring)env->CallObjectMethod(jUuid, gUUIDMethods.toString); |
| 582 | nUuidString = env->GetStringUTFChars(jUuidString, NULL); |
| 583 | SoundTrigger::stringToGuid(nUuidString, &nVendorUuid); |
| 584 | env->ReleaseStringUTFChars(jUuidString, nUuidString); |
| 585 | env->DeleteLocalRef(jUuidString); |
| 586 | } else { |
| 587 | SoundTrigger::stringToGuid("00000000-0000-0000-0000-000000000000", &nVendorUuid); |
| 588 | } |
| 589 | |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 590 | jData = (jbyteArray)env->GetObjectField(jSoundModel, gSoundModelFields.data); |
| 591 | if (jData == NULL) { |
| 592 | status = SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 593 | goto exit; |
| 594 | } |
| 595 | size = env->GetArrayLength(jData); |
| 596 | |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 597 | nData = env->GetByteArrayElements(jData, NULL); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 598 | if (jData == NULL) { |
| 599 | status = SOUNDTRIGGER_STATUS_ERROR; |
| 600 | goto exit; |
| 601 | } |
| 602 | |
| 603 | memoryDealer = new MemoryDealer(offset + size, "SoundTrigge-JNI::LoadModel"); |
| 604 | if (memoryDealer == 0) { |
| 605 | status = SOUNDTRIGGER_STATUS_ERROR; |
| 606 | goto exit; |
| 607 | } |
| 608 | memory = memoryDealer->allocate(offset + size); |
Ytai Ben-Tsvi | 2c9d8f6 | 2019-09-05 15:14:31 -0700 | [diff] [blame] | 609 | if (memory == 0 || memory->unsecurePointer() == NULL) { |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 610 | status = SOUNDTRIGGER_STATUS_ERROR; |
| 611 | goto exit; |
| 612 | } |
| 613 | |
Ytai Ben-Tsvi | 2c9d8f6 | 2019-09-05 15:14:31 -0700 | [diff] [blame] | 614 | nSoundModel = (struct sound_trigger_sound_model *)memory->unsecurePointer(); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 615 | |
| 616 | nSoundModel->type = type; |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 617 | nSoundModel->uuid = nUuid; |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 618 | nSoundModel->vendor_uuid = nVendorUuid; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 619 | nSoundModel->data_size = size; |
| 620 | nSoundModel->data_offset = offset; |
| 621 | memcpy((char *)nSoundModel + offset, nData, size); |
| 622 | if (type == SOUND_MODEL_TYPE_KEYPHRASE) { |
| 623 | struct sound_trigger_phrase_sound_model *phraseModel = |
| 624 | (struct sound_trigger_phrase_sound_model *)nSoundModel; |
| 625 | |
| 626 | jobjectArray jPhrases = |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 627 | (jobjectArray)env->GetObjectField(jSoundModel, gKeyphraseSoundModelFields.keyphrases); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 628 | if (jPhrases == NULL) { |
| 629 | status = SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 630 | goto exit; |
| 631 | } |
| 632 | |
| 633 | size_t numPhrases = env->GetArrayLength(jPhrases); |
| 634 | phraseModel->num_phrases = numPhrases; |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 635 | ALOGV("loadSoundModel numPhrases %zu", numPhrases); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 636 | for (size_t i = 0; i < numPhrases; i++) { |
| 637 | jobject jPhrase = env->GetObjectArrayElement(jPhrases, i); |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 638 | phraseModel->phrases[i].id = |
| 639 | env->GetIntField(jPhrase,gKeyphraseFields.id); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 640 | phraseModel->phrases[i].recognition_mode = |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 641 | env->GetIntField(jPhrase,gKeyphraseFields.recognitionModes); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 642 | |
| 643 | jintArray jUsers = (jintArray)env->GetObjectField(jPhrase, gKeyphraseFields.users); |
| 644 | phraseModel->phrases[i].num_users = env->GetArrayLength(jUsers); |
| 645 | jint *nUsers = env->GetIntArrayElements(jUsers, NULL); |
| 646 | memcpy(phraseModel->phrases[i].users, |
| 647 | nUsers, |
| 648 | phraseModel->phrases[i].num_users * sizeof(int)); |
| 649 | env->ReleaseIntArrayElements(jUsers, nUsers, 0); |
| 650 | env->DeleteLocalRef(jUsers); |
| 651 | |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 652 | jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.locale); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 653 | const char *nLocale = env->GetStringUTFChars(jLocale, NULL); |
| 654 | strncpy(phraseModel->phrases[i].locale, |
| 655 | nLocale, |
| 656 | SOUND_TRIGGER_MAX_LOCALE_LEN); |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 657 | jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.text); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 658 | const char *nText = env->GetStringUTFChars(jText, NULL); |
| 659 | strncpy(phraseModel->phrases[i].text, |
| 660 | nText, |
| 661 | SOUND_TRIGGER_MAX_STRING_LEN); |
| 662 | |
| 663 | env->ReleaseStringUTFChars(jLocale, nLocale); |
| 664 | env->DeleteLocalRef(jLocale); |
| 665 | env->ReleaseStringUTFChars(jText, nText); |
| 666 | env->DeleteLocalRef(jText); |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 667 | ALOGV("loadSoundModel phrases %zu text %s locale %s", |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 668 | i, phraseModel->phrases[i].text, phraseModel->phrases[i].locale); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 669 | env->DeleteLocalRef(jPhrase); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 670 | } |
| 671 | env->DeleteLocalRef(jPhrases); |
Ryan Bavetta | ee3fc89 | 2016-01-26 20:49:28 -0800 | [diff] [blame] | 672 | } else if (type == SOUND_MODEL_TYPE_GENERIC) { |
| 673 | /* No initialization needed */ |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 674 | } |
| 675 | status = module->loadSoundModel(memory, &handle); |
| 676 | ALOGV("loadSoundModel status %d handle %d", status, handle); |
| 677 | |
| 678 | exit: |
| 679 | if (nHandle != NULL) { |
| 680 | nHandle[0] = (jint)handle; |
| 681 | env->ReleaseIntArrayElements(jHandle, nHandle, NULL); |
| 682 | } |
| 683 | if (nData != NULL) { |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 684 | env->ReleaseByteArrayElements(jData, nData, NULL); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 685 | } |
| 686 | return status; |
| 687 | } |
| 688 | |
| 689 | static jint |
| 690 | android_hardware_SoundTrigger_unloadSoundModel(JNIEnv *env, jobject thiz, |
| 691 | jint jHandle) |
| 692 | { |
| 693 | jint status = SOUNDTRIGGER_STATUS_OK; |
| 694 | ALOGV("unloadSoundModel"); |
| 695 | sp<SoundTrigger> module = getSoundTrigger(env, thiz); |
| 696 | if (module == NULL) { |
| 697 | return SOUNDTRIGGER_STATUS_ERROR; |
| 698 | } |
| 699 | status = module->unloadSoundModel((sound_model_handle_t)jHandle); |
| 700 | |
| 701 | return status; |
| 702 | } |
| 703 | |
| 704 | static jint |
| 705 | android_hardware_SoundTrigger_startRecognition(JNIEnv *env, jobject thiz, |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 706 | jint jHandle, jobject jConfig) |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 707 | { |
| 708 | jint status = SOUNDTRIGGER_STATUS_OK; |
| 709 | ALOGV("startRecognition"); |
| 710 | sp<SoundTrigger> module = getSoundTrigger(env, thiz); |
| 711 | if (module == NULL) { |
| 712 | return SOUNDTRIGGER_STATUS_ERROR; |
| 713 | } |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 714 | |
| 715 | if (!env->IsInstanceOf(jConfig, gRecognitionConfigClass)) { |
| 716 | return SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 717 | } |
| 718 | |
| 719 | jbyteArray jData = (jbyteArray)env->GetObjectField(jConfig, gRecognitionConfigFields.data); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 720 | jsize dataSize = 0; |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 721 | jbyte *nData = NULL; |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 722 | if (jData != NULL) { |
| 723 | dataSize = env->GetArrayLength(jData); |
| 724 | if (dataSize == 0) { |
| 725 | return SOUNDTRIGGER_STATUS_BAD_VALUE; |
| 726 | } |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 727 | nData = env->GetByteArrayElements(jData, NULL); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 728 | if (nData == NULL) { |
| 729 | return SOUNDTRIGGER_STATUS_ERROR; |
| 730 | } |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 731 | } |
| 732 | |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 733 | size_t totalSize = sizeof(struct sound_trigger_recognition_config) + dataSize; |
| 734 | sp<MemoryDealer> memoryDealer = |
| 735 | new MemoryDealer(totalSize, "SoundTrigge-JNI::StartRecognition"); |
| 736 | if (memoryDealer == 0) { |
| 737 | return SOUNDTRIGGER_STATUS_ERROR; |
| 738 | } |
| 739 | sp<IMemory> memory = memoryDealer->allocate(totalSize); |
Ytai Ben-Tsvi | 2c9d8f6 | 2019-09-05 15:14:31 -0700 | [diff] [blame] | 740 | if (memory == 0 || memory->unsecurePointer() == NULL) { |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 741 | return SOUNDTRIGGER_STATUS_ERROR; |
| 742 | } |
| 743 | if (dataSize != 0) { |
Ytai Ben-Tsvi | 2c9d8f6 | 2019-09-05 15:14:31 -0700 | [diff] [blame] | 744 | memcpy((char *)memory->unsecurePointer() + sizeof(struct sound_trigger_recognition_config), |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 745 | nData, |
| 746 | dataSize); |
| 747 | env->ReleaseByteArrayElements(jData, nData, 0); |
| 748 | } |
| 749 | env->DeleteLocalRef(jData); |
| 750 | struct sound_trigger_recognition_config *config = |
Ytai Ben-Tsvi | 2c9d8f6 | 2019-09-05 15:14:31 -0700 | [diff] [blame] | 751 | (struct sound_trigger_recognition_config *)memory->unsecurePointer(); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 752 | config->data_size = dataSize; |
| 753 | config->data_offset = sizeof(struct sound_trigger_recognition_config); |
Eric Laurent | 89311c2 | 2015-05-22 10:30:13 -0700 | [diff] [blame] | 754 | config->capture_requested = env->GetBooleanField(jConfig, |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 755 | gRecognitionConfigFields.captureRequested); |
| 756 | |
| 757 | config->num_phrases = 0; |
| 758 | jobjectArray jPhrases = |
| 759 | (jobjectArray)env->GetObjectField(jConfig, gRecognitionConfigFields.keyphrases); |
| 760 | if (jPhrases != NULL) { |
| 761 | config->num_phrases = env->GetArrayLength(jPhrases); |
| 762 | } |
| 763 | ALOGV("startRecognition num phrases %d", config->num_phrases); |
| 764 | for (size_t i = 0; i < config->num_phrases; i++) { |
| 765 | jobject jPhrase = env->GetObjectArrayElement(jPhrases, i); |
| 766 | config->phrases[i].id = env->GetIntField(jPhrase, |
| 767 | gKeyphraseRecognitionExtraFields.id); |
| 768 | config->phrases[i].recognition_modes = env->GetIntField(jPhrase, |
| 769 | gKeyphraseRecognitionExtraFields.recognitionModes); |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 770 | config->phrases[i].confidence_level = env->GetIntField(jPhrase, |
| 771 | gKeyphraseRecognitionExtraFields.coarseConfidenceLevel); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 772 | config->phrases[i].num_levels = 0; |
| 773 | jobjectArray jConfidenceLevels = (jobjectArray)env->GetObjectField(jPhrase, |
| 774 | gKeyphraseRecognitionExtraFields.confidenceLevels); |
| 775 | if (jConfidenceLevels != NULL) { |
| 776 | config->phrases[i].num_levels = env->GetArrayLength(jConfidenceLevels); |
| 777 | } |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 778 | ALOGV("startRecognition phrase %zu num_levels %d", i, config->phrases[i].num_levels); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 779 | for (size_t j = 0; j < config->phrases[i].num_levels; j++) { |
| 780 | jobject jConfidenceLevel = env->GetObjectArrayElement(jConfidenceLevels, j); |
| 781 | config->phrases[i].levels[j].user_id = env->GetIntField(jConfidenceLevel, |
| 782 | gConfidenceLevelFields.userId); |
| 783 | config->phrases[i].levels[j].level = env->GetIntField(jConfidenceLevel, |
| 784 | gConfidenceLevelFields.confidenceLevel); |
| 785 | env->DeleteLocalRef(jConfidenceLevel); |
| 786 | } |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 787 | ALOGV("startRecognition phrases %zu", i); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 788 | env->DeleteLocalRef(jConfidenceLevels); |
| 789 | env->DeleteLocalRef(jPhrase); |
| 790 | } |
| 791 | env->DeleteLocalRef(jPhrases); |
| 792 | |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 793 | status = module->startRecognition(jHandle, memory); |
| 794 | return status; |
| 795 | } |
| 796 | |
| 797 | static jint |
| 798 | android_hardware_SoundTrigger_stopRecognition(JNIEnv *env, jobject thiz, |
| 799 | jint jHandle) |
| 800 | { |
| 801 | jint status = SOUNDTRIGGER_STATUS_OK; |
| 802 | ALOGV("stopRecognition"); |
| 803 | sp<SoundTrigger> module = getSoundTrigger(env, thiz); |
| 804 | if (module == NULL) { |
| 805 | return SOUNDTRIGGER_STATUS_ERROR; |
| 806 | } |
| 807 | status = module->stopRecognition(jHandle); |
| 808 | return status; |
| 809 | } |
| 810 | |
mike dooley | b2ab04a | 2018-11-07 15:48:54 +0100 | [diff] [blame] | 811 | static jint |
Michael Dooley | 291751e | 2018-10-16 19:53:29 +0000 | [diff] [blame] | 812 | android_hardware_SoundTrigger_getModelState(JNIEnv *env, jobject thiz, |
| 813 | jint jHandle) |
| 814 | { |
mike dooley | b2ab04a | 2018-11-07 15:48:54 +0100 | [diff] [blame] | 815 | jint status = SOUNDTRIGGER_STATUS_OK; |
Michael Dooley | 291751e | 2018-10-16 19:53:29 +0000 | [diff] [blame] | 816 | ALOGV("getModelState"); |
| 817 | sp<SoundTrigger> module = getSoundTrigger(env, thiz); |
| 818 | if (module == NULL) { |
mike dooley | b2ab04a | 2018-11-07 15:48:54 +0100 | [diff] [blame] | 819 | return SOUNDTRIGGER_STATUS_ERROR; |
Michael Dooley | 291751e | 2018-10-16 19:53:29 +0000 | [diff] [blame] | 820 | } |
mike dooley | b2ab04a | 2018-11-07 15:48:54 +0100 | [diff] [blame] | 821 | status = module->getModelState(jHandle); |
| 822 | return status; |
Michael Dooley | 291751e | 2018-10-16 19:53:29 +0000 | [diff] [blame] | 823 | } |
| 824 | |
Daniel Micay | 76f6a86 | 2015-09-19 17:31:01 -0400 | [diff] [blame] | 825 | static const JNINativeMethod gMethods[] = { |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 826 | {"listModules", |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 827 | "(Ljava/lang/String;Ljava/util/ArrayList;)I", |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 828 | (void *)android_hardware_SoundTrigger_listModules}, |
| 829 | }; |
| 830 | |
| 831 | |
Daniel Micay | 76f6a86 | 2015-09-19 17:31:01 -0400 | [diff] [blame] | 832 | static const JNINativeMethod gModuleMethods[] = { |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 833 | {"native_setup", |
jiabin | 1f4b4dd | 2019-03-18 18:07:03 -0700 | [diff] [blame] | 834 | "(Ljava/lang/String;Ljava/lang/Object;)V", |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 835 | (void *)android_hardware_SoundTrigger_setup}, |
| 836 | {"native_finalize", |
| 837 | "()V", |
| 838 | (void *)android_hardware_SoundTrigger_finalize}, |
| 839 | {"detach", |
| 840 | "()V", |
| 841 | (void *)android_hardware_SoundTrigger_detach}, |
| 842 | {"loadSoundModel", |
| 843 | "(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;[I)I", |
| 844 | (void *)android_hardware_SoundTrigger_loadSoundModel}, |
| 845 | {"unloadSoundModel", |
| 846 | "(I)I", |
| 847 | (void *)android_hardware_SoundTrigger_unloadSoundModel}, |
| 848 | {"startRecognition", |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 849 | "(ILandroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I", |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 850 | (void *)android_hardware_SoundTrigger_startRecognition}, |
| 851 | {"stopRecognition", |
| 852 | "(I)I", |
| 853 | (void *)android_hardware_SoundTrigger_stopRecognition}, |
Michael Dooley | 291751e | 2018-10-16 19:53:29 +0000 | [diff] [blame] | 854 | {"getModelState", |
mike dooley | b2ab04a | 2018-11-07 15:48:54 +0100 | [diff] [blame] | 855 | "(I)I", |
Michael Dooley | 291751e | 2018-10-16 19:53:29 +0000 | [diff] [blame] | 856 | (void *)android_hardware_SoundTrigger_getModelState}, |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 857 | }; |
| 858 | |
| 859 | int register_android_hardware_SoundTrigger(JNIEnv *env) |
| 860 | { |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 861 | jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); |
| 862 | gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); |
| 863 | gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 864 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 865 | jclass uuidClass = FindClassOrDie(env, "java/util/UUID"); |
| 866 | gUUIDClass = MakeGlobalRefOrDie(env, uuidClass); |
| 867 | gUUIDMethods.toString = GetMethodIDOrDie(env, uuidClass, "toString", "()Ljava/lang/String;"); |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 868 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 869 | jclass lClass = FindClassOrDie(env, kSoundTriggerClassPathName); |
| 870 | gSoundTriggerClass = MakeGlobalRefOrDie(env, lClass); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 871 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 872 | jclass moduleClass = FindClassOrDie(env, kModuleClassPathName); |
| 873 | gModuleClass = MakeGlobalRefOrDie(env, moduleClass); |
| 874 | gPostEventFromNative = GetStaticMethodIDOrDie(env, moduleClass, "postEventFromNative", |
| 875 | "(Ljava/lang/Object;IIILjava/lang/Object;)V"); |
| 876 | gModuleFields.mNativeContext = GetFieldIDOrDie(env, moduleClass, "mNativeContext", "J"); |
| 877 | gModuleFields.mId = GetFieldIDOrDie(env, moduleClass, "mId", "I"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 878 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 879 | jclass modulePropertiesClass = FindClassOrDie(env, kModulePropertiesClassPathName); |
| 880 | gModulePropertiesClass = MakeGlobalRefOrDie(env, modulePropertiesClass); |
| 881 | gModulePropertiesCstor = GetMethodIDOrDie(env, modulePropertiesClass, "<init>", |
| 882 | "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZIZ)V"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 883 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 884 | jclass soundModelClass = FindClassOrDie(env, kSoundModelClassPathName); |
| 885 | gSoundModelClass = MakeGlobalRefOrDie(env, soundModelClass); |
| 886 | gSoundModelFields.uuid = GetFieldIDOrDie(env, soundModelClass, "uuid", "Ljava/util/UUID;"); |
| 887 | gSoundModelFields.vendorUuid = GetFieldIDOrDie(env, soundModelClass, "vendorUuid", |
| 888 | "Ljava/util/UUID;"); |
| 889 | gSoundModelFields.data = GetFieldIDOrDie(env, soundModelClass, "data", "[B"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 890 | |
Ryan Bavetta | ee3fc89 | 2016-01-26 20:49:28 -0800 | [diff] [blame] | 891 | jclass genericSoundModelClass = FindClassOrDie(env, kGenericSoundModelClassPathName); |
| 892 | gGenericSoundModelClass = MakeGlobalRefOrDie(env, genericSoundModelClass); |
| 893 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 894 | jclass keyphraseClass = FindClassOrDie(env, kKeyphraseClassPathName); |
| 895 | gKeyphraseClass = MakeGlobalRefOrDie(env, keyphraseClass); |
| 896 | gKeyphraseFields.id = GetFieldIDOrDie(env, keyphraseClass, "id", "I"); |
| 897 | gKeyphraseFields.recognitionModes = GetFieldIDOrDie(env, keyphraseClass, "recognitionModes", |
| 898 | "I"); |
| 899 | gKeyphraseFields.locale = GetFieldIDOrDie(env, keyphraseClass, "locale", "Ljava/lang/String;"); |
| 900 | gKeyphraseFields.text = GetFieldIDOrDie(env, keyphraseClass, "text", "Ljava/lang/String;"); |
| 901 | gKeyphraseFields.users = GetFieldIDOrDie(env, keyphraseClass, "users", "[I"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 902 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 903 | jclass keyphraseSoundModelClass = FindClassOrDie(env, kKeyphraseSoundModelClassPathName); |
| 904 | gKeyphraseSoundModelClass = MakeGlobalRefOrDie(env, keyphraseSoundModelClass); |
| 905 | gKeyphraseSoundModelFields.keyphrases = GetFieldIDOrDie(env, keyphraseSoundModelClass, |
Sandeep Siddhartha | d4233c6 | 2014-06-12 18:31:19 -0700 | [diff] [blame] | 906 | "keyphrases", |
| 907 | "[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 908 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 909 | jclass recognitionEventClass = FindClassOrDie(env, kRecognitionEventClassPathName); |
| 910 | gRecognitionEventClass = MakeGlobalRefOrDie(env, recognitionEventClass); |
| 911 | gRecognitionEventCstor = GetMethodIDOrDie(env, recognitionEventClass, "<init>", |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 912 | "(IIZIIIZLandroid/media/AudioFormat;[B)V"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 913 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 914 | jclass keyphraseRecognitionEventClass = FindClassOrDie(env, |
| 915 | kKeyphraseRecognitionEventClassPathName); |
| 916 | gKeyphraseRecognitionEventClass = MakeGlobalRefOrDie(env, keyphraseRecognitionEventClass); |
| 917 | gKeyphraseRecognitionEventCstor = GetMethodIDOrDie(env, keyphraseRecognitionEventClass, "<init>", |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 918 | "(IIZIIIZLandroid/media/AudioFormat;[B[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 919 | |
Ryan Bavetta | ee3fc89 | 2016-01-26 20:49:28 -0800 | [diff] [blame] | 920 | jclass genericRecognitionEventClass = FindClassOrDie(env, |
| 921 | kGenericRecognitionEventClassPathName); |
| 922 | gGenericRecognitionEventClass = MakeGlobalRefOrDie(env, genericRecognitionEventClass); |
| 923 | gGenericRecognitionEventCstor = GetMethodIDOrDie(env, genericRecognitionEventClass, "<init>", |
| 924 | "(IIZIIIZLandroid/media/AudioFormat;[B)V"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 925 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 926 | jclass keyRecognitionConfigClass = FindClassOrDie(env, kRecognitionConfigClassPathName); |
| 927 | gRecognitionConfigClass = MakeGlobalRefOrDie(env, keyRecognitionConfigClass); |
| 928 | gRecognitionConfigFields.captureRequested = GetFieldIDOrDie(env, keyRecognitionConfigClass, |
| 929 | "captureRequested", "Z"); |
| 930 | gRecognitionConfigFields.keyphrases = GetFieldIDOrDie(env, keyRecognitionConfigClass, |
| 931 | "keyphrases", "[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;"); |
| 932 | gRecognitionConfigFields.data = GetFieldIDOrDie(env, keyRecognitionConfigClass, "data", "[B"); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 933 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 934 | jclass keyphraseRecognitionExtraClass = FindClassOrDie(env, |
| 935 | kKeyphraseRecognitionExtraClassPathName); |
| 936 | gKeyphraseRecognitionExtraClass = MakeGlobalRefOrDie(env, keyphraseRecognitionExtraClass); |
| 937 | gKeyphraseRecognitionExtraCstor = GetMethodIDOrDie(env, keyphraseRecognitionExtraClass, |
| 938 | "<init>", "(III[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;)V"); |
| 939 | gKeyphraseRecognitionExtraFields.id = GetFieldIDOrDie(env, gKeyphraseRecognitionExtraClass, |
| 940 | "id", "I"); |
| 941 | gKeyphraseRecognitionExtraFields.recognitionModes = GetFieldIDOrDie(env, |
| 942 | gKeyphraseRecognitionExtraClass, "recognitionModes", "I"); |
| 943 | gKeyphraseRecognitionExtraFields.coarseConfidenceLevel = GetFieldIDOrDie(env, |
| 944 | gKeyphraseRecognitionExtraClass, "coarseConfidenceLevel", "I"); |
| 945 | gKeyphraseRecognitionExtraFields.confidenceLevels = GetFieldIDOrDie(env, |
| 946 | gKeyphraseRecognitionExtraClass, "confidenceLevels", |
| 947 | "[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;"); |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 948 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 949 | jclass confidenceLevelClass = FindClassOrDie(env, kConfidenceLevelClassPathName); |
| 950 | gConfidenceLevelClass = MakeGlobalRefOrDie(env, confidenceLevelClass); |
| 951 | gConfidenceLevelCstor = GetMethodIDOrDie(env, confidenceLevelClass, "<init>", "(II)V"); |
| 952 | gConfidenceLevelFields.userId = GetFieldIDOrDie(env, confidenceLevelClass, "userId", "I"); |
| 953 | gConfidenceLevelFields.confidenceLevel = GetFieldIDOrDie(env, confidenceLevelClass, |
Eric Laurent | 013f66b | 2014-07-06 16:35:00 -0700 | [diff] [blame] | 954 | "confidenceLevel", "I"); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 955 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 956 | jclass audioFormatClass = FindClassOrDie(env, kAudioFormatClassPathName); |
| 957 | gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass); |
Andy Hung | a9470c1 | 2015-01-29 17:16:03 -0800 | [diff] [blame] | 958 | gAudioFormatCstor = GetMethodIDOrDie(env, audioFormatClass, "<init>", "(IIII)V"); |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 959 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 960 | jclass soundModelEventClass = FindClassOrDie(env, kSoundModelEventClassPathName); |
| 961 | gSoundModelEventClass = MakeGlobalRefOrDie(env, soundModelEventClass); |
| 962 | gSoundModelEventCstor = GetMethodIDOrDie(env, soundModelEventClass, "<init>", "(II[B)V"); |
Eric Laurent | d3b8223 | 2014-07-30 08:57:39 -0700 | [diff] [blame] | 963 | |
| 964 | |
Andreas Gampe | ed6b9df | 2014-11-20 22:02:20 -0800 | [diff] [blame] | 965 | RegisterMethodsOrDie(env, kSoundTriggerClassPathName, gMethods, NELEM(gMethods)); |
| 966 | return RegisterMethodsOrDie(env, kModuleClassPathName, gModuleMethods, NELEM(gModuleMethods)); |
Eric Laurent | 60b62bc | 2014-04-18 17:50:49 -0700 | [diff] [blame] | 967 | } |