160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent/*
260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent**
360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** Copyright 2014, The Android Open Source Project
460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent**
560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** Licensed under the Apache License, Version 2.0 (the "License");
660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** you may not use this file except in compliance with the License.
760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** You may obtain a copy of the License at
860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent**
960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent**     http://www.apache.org/licenses/LICENSE-2.0
1060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent**
1160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** Unless required by applicable law or agreed to in writing, software
1260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** distributed under the License is distributed on an "AS IS" BASIS,
1360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** See the License for the specific language governing permissions and
1560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent** limitations under the License.
1660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent*/
1760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
1860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent//#define LOG_NDEBUG 0
1960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#define LOG_TAG "SoundTrigger-JNI"
2060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include <utils/Log.h>
2160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
2260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include "jni.h"
2360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include "JNIHelp.h"
24ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
2560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include <system/sound_trigger.h>
2660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include <soundtrigger/SoundTriggerCallback.h>
2760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include <soundtrigger/SoundTrigger.h>
2860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include <utils/RefBase.h>
2960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include <utils/Vector.h>
3060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include <binder/IMemory.h>
3160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent#include <binder/MemoryDealer.h>
32d3b8223377b8046280e4c09e728edc600171f941Eric Laurent#include "android_media_AudioFormat.h"
3360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
3460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentusing namespace android;
3560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
3660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jclass gArrayListClass;
3760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic struct {
3860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jmethodID    add;
3960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent} gArrayListMethods;
4060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
41d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic jclass gUUIDClass;
42d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic struct {
43d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    jmethodID    toString;
44d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha} gUUIDMethods;
45d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha
4660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic const char* const kSoundTriggerClassPathName = "android/hardware/soundtrigger/SoundTrigger";
4760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jclass gSoundTriggerClass;
4860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
4960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic const char* const kModuleClassPathName = "android/hardware/soundtrigger/SoundTriggerModule";
5060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jclass gModuleClass;
5160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic struct {
5260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jfieldID    mNativeContext;
5360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jfieldID    mId;
5460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent} gModuleFields;
5560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jmethodID   gPostEventFromNative;
5660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
5760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic const char* const kModulePropertiesClassPathName =
5860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                     "android/hardware/soundtrigger/SoundTrigger$ModuleProperties";
5960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jclass gModulePropertiesClass;
6060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jmethodID   gModulePropertiesCstor;
6160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
6260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic const char* const kSoundModelClassPathName =
6360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                     "android/hardware/soundtrigger/SoundTrigger$SoundModel";
6460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jclass gSoundModelClass;
6560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic struct {
66d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    jfieldID    uuid;
67d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    jfieldID    vendorUuid;
6860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jfieldID    data;
6960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent} gSoundModelFields;
7060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
71ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavettastatic const char* const kGenericSoundModelClassPathName =
72ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta                                     "android/hardware/soundtrigger/SoundTrigger$GenericSoundModel";
73ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavettastatic jclass gGenericSoundModelClass;
74ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta
75d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic const char* const kKeyphraseClassPathName =
76d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                                     "android/hardware/soundtrigger/SoundTrigger$Keyphrase";
77d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic jclass gKeyphraseClass;
7860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic struct {
79d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    jfieldID id;
8060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jfieldID recognitionModes;
8160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jfieldID locale;
8260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jfieldID text;
83013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID users;
84d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha} gKeyphraseFields;
8560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
86d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic const char* const kKeyphraseSoundModelClassPathName =
87d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                                 "android/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel";
88d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic jclass gKeyphraseSoundModelClass;
8960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic struct {
90d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    jfieldID    keyphrases;
91d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha} gKeyphraseSoundModelFields;
9260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
93013f66b92db609fceeff9c8171daca13d057cc95Eric Laurentstatic const char* const kRecognitionConfigClassPathName =
94013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                     "android/hardware/soundtrigger/SoundTrigger$RecognitionConfig";
95013f66b92db609fceeff9c8171daca13d057cc95Eric Laurentstatic jclass gRecognitionConfigClass;
96013f66b92db609fceeff9c8171daca13d057cc95Eric Laurentstatic struct {
97013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID captureRequested;
98013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID keyphrases;
99013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID data;
100013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent} gRecognitionConfigFields;
10160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
10260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic const char* const kRecognitionEventClassPathName =
10360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                     "android/hardware/soundtrigger/SoundTrigger$RecognitionEvent";
10460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jclass gRecognitionEventClass;
10560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jmethodID   gRecognitionEventCstor;
10660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
107d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic const char* const kKeyphraseRecognitionEventClassPathName =
108d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                             "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent";
109d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic jclass gKeyphraseRecognitionEventClass;
110d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic jmethodID   gKeyphraseRecognitionEventCstor;
11160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
112ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavettastatic const char* const kGenericRecognitionEventClassPathName =
113ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta                             "android/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent";
114ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavettastatic jclass gGenericRecognitionEventClass;
115ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavettastatic jmethodID   gGenericRecognitionEventCstor;
116ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta
117d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic const char* const kKeyphraseRecognitionExtraClassPathName =
118d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                             "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra";
119d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic jclass gKeyphraseRecognitionExtraClass;
120d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddharthastatic jmethodID   gKeyphraseRecognitionExtraCstor;
121013f66b92db609fceeff9c8171daca13d057cc95Eric Laurentstatic struct {
122013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID id;
123013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID recognitionModes;
124d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    jfieldID coarseConfidenceLevel;
125013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID confidenceLevels;
126013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent} gKeyphraseRecognitionExtraFields;
127013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
128013f66b92db609fceeff9c8171daca13d057cc95Eric Laurentstatic const char* const kConfidenceLevelClassPathName =
129013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                             "android/hardware/soundtrigger/SoundTrigger$ConfidenceLevel";
130013f66b92db609fceeff9c8171daca13d057cc95Eric Laurentstatic jclass gConfidenceLevelClass;
131013f66b92db609fceeff9c8171daca13d057cc95Eric Laurentstatic jmethodID   gConfidenceLevelCstor;
132013f66b92db609fceeff9c8171daca13d057cc95Eric Laurentstatic struct {
133013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID userId;
134013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jfieldID confidenceLevel;
135013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent} gConfidenceLevelFields;
13660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
137d3b8223377b8046280e4c09e728edc600171f941Eric Laurentstatic const char* const kAudioFormatClassPathName =
138d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                             "android/media/AudioFormat";
139d3b8223377b8046280e4c09e728edc600171f941Eric Laurentstatic jclass gAudioFormatClass;
140d3b8223377b8046280e4c09e728edc600171f941Eric Laurentstatic jmethodID gAudioFormatCstor;
141d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
142d3b8223377b8046280e4c09e728edc600171f941Eric Laurentstatic const char* const kSoundModelEventClassPathName =
143d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                     "android/hardware/soundtrigger/SoundTrigger$SoundModelEvent";
144d3b8223377b8046280e4c09e728edc600171f941Eric Laurentstatic jclass gSoundModelEventClass;
145d3b8223377b8046280e4c09e728edc600171f941Eric Laurentstatic jmethodID   gSoundModelEventCstor;
146d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
14760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic Mutex gLock;
14860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
14960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentenum {
15060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_STATUS_OK = 0,
15160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_STATUS_ERROR = INT_MIN,
15260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_PERMISSION_DENIED = -1,
15360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_STATUS_NO_INIT = -19,
15460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_STATUS_BAD_VALUE = -22,
15560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_STATUS_DEAD_OBJECT = -32,
15660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_INVALID_OPERATION = -38,
15760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent};
15860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
15960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentenum  {
16060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_EVENT_RECOGNITION = 1,
16160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SOUNDTRIGGER_EVENT_SERVICE_DIED = 2,
162d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    SOUNDTRIGGER_EVENT_SOUNDMODEL = 3,
163d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    SOUNDTRIGGER_EVENT_SERVICE_STATE_CHANGE = 4,
16460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent};
16560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
16660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent// ----------------------------------------------------------------------------
16760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent// ref-counted object for callbacks
16860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentclass JNISoundTriggerCallback: public SoundTriggerCallback
16960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
17060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentpublic:
17160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
17260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ~JNISoundTriggerCallback();
17360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
17460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event);
175d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    virtual void onSoundModelEvent(struct sound_trigger_model_event *event);
176d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    virtual void onServiceStateChange(sound_trigger_service_state_t state);
17760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    virtual void onServiceDied();
17860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
17960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentprivate:
18060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jclass      mClass;     // Reference to SoundTrigger class
18160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jobject     mObject;    // Weak ref to SoundTrigger Java object to call on
18260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent};
18360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
18460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric LaurentJNISoundTriggerCallback::JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
18560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
18660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
18760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    // Hold onto the SoundTriggerModule class for use in calling the static method
18860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    // that posts events to the application thread.
18960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jclass clazz = env->GetObjectClass(thiz);
19060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (clazz == NULL) {
19160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        ALOGE("Can't find class %s", kModuleClassPathName);
19260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return;
19360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
19460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    mClass = (jclass)env->NewGlobalRef(clazz);
19560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
19660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    // We use a weak reference so the SoundTriggerModule object can be garbage collected.
19760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    // The reference is only used as a proxy for callbacks.
19860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    mObject  = env->NewGlobalRef(weak_thiz);
19960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
20060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
20160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric LaurentJNISoundTriggerCallback::~JNISoundTriggerCallback()
20260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
20360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    // remove global references
20460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    JNIEnv *env = AndroidRuntime::getJNIEnv();
20560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    env->DeleteGlobalRef(mObject);
20660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    env->DeleteGlobalRef(mClass);
20760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
20860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
20960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentvoid JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognition_event *event)
21060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
21160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    JNIEnv *env = AndroidRuntime::getJNIEnv();
212d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    jobject jEvent = NULL;
21360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jbyteArray jData = NULL;
214d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
21560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (event->data_size) {
21660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jData = env->NewByteArray(event->data_size);
21760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jbyte *nData = env->GetByteArrayElements(jData, NULL);
21860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        memcpy(nData, (char *)event + event->data_offset, event->data_size);
21960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->ReleaseByteArrayElements(jData, nData, 0);
22060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
22160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
222d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    jobject jAudioFormat = NULL;
22339fcca0a503658f91a14b4b1d35dfc4ac9fce9d9Eric Laurent    if (event->trigger_in_data || event->capture_available) {
224d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        jAudioFormat = env->NewObject(gAudioFormatClass,
225d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                    gAudioFormatCstor,
226d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                    audioFormatFromNative(event->audio_config.format),
227d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                    event->audio_config.sample_rate,
228d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                    inChannelMaskFromNative(event->audio_config.channel_mask));
229d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
230d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    }
23160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (event->type == SOUND_MODEL_TYPE_KEYPHRASE) {
23260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        struct sound_trigger_phrase_recognition_event *phraseEvent =
23360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                (struct sound_trigger_phrase_recognition_event *)event;
23460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
23560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jobjectArray jExtras = env->NewObjectArray(phraseEvent->num_phrases,
236d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                                                  gKeyphraseRecognitionExtraClass, NULL);
23760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        if (jExtras == NULL) {
23860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            return;
23960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
24060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
24160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        for (size_t i = 0; i < phraseEvent->num_phrases; i++) {
242013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            jobjectArray jConfidenceLevels = env->NewObjectArray(
243013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                        phraseEvent->phrase_extras[i].num_levels,
244013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                        gConfidenceLevelClass, NULL);
245013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
24660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            if (jConfidenceLevels == NULL) {
24760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                return;
24860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            }
249013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            for (size_t j = 0; j < phraseEvent->phrase_extras[i].num_levels; j++) {
250013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                jobject jConfidenceLevel = env->NewObject(gConfidenceLevelClass,
251013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                  gConfidenceLevelCstor,
252013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                  phraseEvent->phrase_extras[i].levels[j].user_id,
253013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                  phraseEvent->phrase_extras[i].levels[j].level);
254013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                env->SetObjectArrayElement(jConfidenceLevels, j, jConfidenceLevel);
255013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                env->DeleteLocalRef(jConfidenceLevel);
256013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            }
257013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
258d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha            jobject jNewExtra = env->NewObject(gKeyphraseRecognitionExtraClass,
259d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                                               gKeyphraseRecognitionExtraCstor,
260013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                               phraseEvent->phrase_extras[i].id,
261013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                               phraseEvent->phrase_extras[i].recognition_modes,
262d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                               phraseEvent->phrase_extras[i].confidence_level,
263013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                               jConfidenceLevels);
26460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
26560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            if (jNewExtra == NULL) {
26660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                return;
26760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            }
26860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            env->SetObjectArrayElement(jExtras, i, jNewExtra);
269013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            env->DeleteLocalRef(jNewExtra);
270013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            env->DeleteLocalRef(jConfidenceLevels);
27160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
272d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha        jEvent = env->NewObject(gKeyphraseRecognitionEventClass, gKeyphraseRecognitionEventCstor,
27360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                event->status, event->model, event->capture_available,
274d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                event->capture_session, event->capture_delay_ms,
275d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                event->capture_preamble_ms, event->trigger_in_data,
276d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                jAudioFormat, jData, jExtras);
2778f89feba39be8e705c6b9f550c5af141a9e189daEric Laurent        env->DeleteLocalRef(jExtras);
278ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta    } else if (event->type == SOUND_MODEL_TYPE_GENERIC) {
279ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta        jEvent = env->NewObject(gGenericRecognitionEventClass, gGenericRecognitionEventCstor,
280ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta                                event->status, event->model, event->capture_available,
281ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta                                event->capture_session, event->capture_delay_ms,
282ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta                                event->capture_preamble_ms, event->trigger_in_data,
283ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta                                jAudioFormat, jData);
28460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    } else {
28560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor,
28660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                event->status, event->model, event->capture_available,
287013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                event->capture_session, event->capture_delay_ms,
288d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                event->capture_preamble_ms, event->trigger_in_data,
289d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                jAudioFormat, jData);
2908f89feba39be8e705c6b9f550c5af141a9e189daEric Laurent    }
2918f89feba39be8e705c6b9f550c5af141a9e189daEric Laurent
2928f89feba39be8e705c6b9f550c5af141a9e189daEric Laurent    if (jAudioFormat != NULL) {
293d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        env->DeleteLocalRef(jAudioFormat);
2948f89feba39be8e705c6b9f550c5af141a9e189daEric Laurent    }
2958f89feba39be8e705c6b9f550c5af141a9e189daEric Laurent    if (jData != NULL) {
296d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        env->DeleteLocalRef(jData);
29760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
29860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
29960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
30060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                              SOUNDTRIGGER_EVENT_RECOGNITION, 0, 0, jEvent);
301d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
302d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    env->DeleteLocalRef(jEvent);
303d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    if (env->ExceptionCheck()) {
304d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        ALOGW("An exception occurred while notifying an event.");
305d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        env->ExceptionClear();
306d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    }
307d3b8223377b8046280e4c09e728edc600171f941Eric Laurent}
308d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
309d3b8223377b8046280e4c09e728edc600171f941Eric Laurentvoid JNISoundTriggerCallback::onSoundModelEvent(struct sound_trigger_model_event *event)
310d3b8223377b8046280e4c09e728edc600171f941Eric Laurent{
311d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    JNIEnv *env = AndroidRuntime::getJNIEnv();
312d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    jobject jEvent = NULL;
313d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    jbyteArray jData = NULL;
314d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
315d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    if (event->data_size) {
316d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        jData = env->NewByteArray(event->data_size);
317d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        jbyte *nData = env->GetByteArrayElements(jData, NULL);
318d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        memcpy(nData, (char *)event + event->data_offset, event->data_size);
319d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        env->ReleaseByteArrayElements(jData, nData, 0);
320d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    }
321d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
322d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    jEvent = env->NewObject(gSoundModelEventClass, gSoundModelEventCstor,
323d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                            event->status, event->model, jData);
324d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
325d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    env->DeleteLocalRef(jData);
326d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
327d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                              SOUNDTRIGGER_EVENT_SOUNDMODEL, 0, 0, jEvent);
328d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    env->DeleteLocalRef(jEvent);
329d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    if (env->ExceptionCheck()) {
330d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        ALOGW("An exception occurred while notifying an event.");
331d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        env->ExceptionClear();
332d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    }
333d3b8223377b8046280e4c09e728edc600171f941Eric Laurent}
334d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
335d3b8223377b8046280e4c09e728edc600171f941Eric Laurentvoid JNISoundTriggerCallback::onServiceStateChange(sound_trigger_service_state_t state)
336d3b8223377b8046280e4c09e728edc600171f941Eric Laurent{
337d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    JNIEnv *env = AndroidRuntime::getJNIEnv();
338d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
339d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                        SOUNDTRIGGER_EVENT_SERVICE_STATE_CHANGE, state, 0, NULL);
34060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (env->ExceptionCheck()) {
34160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        ALOGW("An exception occurred while notifying an event.");
34260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->ExceptionClear();
34360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
34460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
34560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
34660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentvoid JNISoundTriggerCallback::onServiceDied()
34760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
34860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    JNIEnv *env = AndroidRuntime::getJNIEnv();
34960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
35060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
35160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                              SOUNDTRIGGER_EVENT_SERVICE_DIED, 0, 0, NULL);
35260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (env->ExceptionCheck()) {
35360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        ALOGW("An exception occurred while notifying an event.");
35460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->ExceptionClear();
35560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
35660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
35760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
35860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent// ----------------------------------------------------------------------------
35960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
36060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic sp<SoundTrigger> getSoundTrigger(JNIEnv* env, jobject thiz)
36160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
36260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    Mutex::Autolock l(gLock);
36360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    SoundTrigger* const st = (SoundTrigger*)env->GetLongField(thiz,
36460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                                         gModuleFields.mNativeContext);
36560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    return sp<SoundTrigger>(st);
36660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
36760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
36860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic sp<SoundTrigger> setSoundTrigger(JNIEnv* env, jobject thiz, const sp<SoundTrigger>& module)
36960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
37060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    Mutex::Autolock l(gLock);
37160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<SoundTrigger> old = (SoundTrigger*)env->GetLongField(thiz,
37260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                                         gModuleFields.mNativeContext);
37360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (module.get()) {
37460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        module->incStrong((void*)setSoundTrigger);
37560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
37660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (old != 0) {
37760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        old->decStrong((void*)setSoundTrigger);
37860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
37960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    env->SetLongField(thiz, gModuleFields.mNativeContext, (jlong)module.get());
38060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    return old;
38160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
38260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
38360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
38460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jint
38560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentandroid_hardware_SoundTrigger_listModules(JNIEnv *env, jobject clazz,
38660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                          jobject jModules)
38760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
38860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("listModules");
38960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
39060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (jModules == NULL) {
39160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        ALOGE("listModules NULL AudioPatch ArrayList");
39260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_BAD_VALUE;
39360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
39460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (!env->IsInstanceOf(jModules, gArrayListClass)) {
39560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        ALOGE("listModules not an arraylist");
39660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_BAD_VALUE;
39760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
39860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
39960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    unsigned int numModules = 0;
40060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    struct sound_trigger_module_descriptor *nModules = NULL;
40160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
40260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    status_t status = SoundTrigger::listModules(nModules, &numModules);
40360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (status != NO_ERROR || numModules == 0) {
40460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return (jint)status;
40560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
40660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
40760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    nModules = (struct sound_trigger_module_descriptor *)
40860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                            calloc(numModules, sizeof(struct sound_trigger_module_descriptor));
40960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
41060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    status = SoundTrigger::listModules(nModules, &numModules);
41160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("listModules SoundTrigger::listModules status %d numModules %d", status, numModules);
41260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
41360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (status != NO_ERROR) {
41460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        numModules = 0;
41560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
41660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
41760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    for (size_t i = 0; i < numModules; i++) {
41860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        char str[SOUND_TRIGGER_MAX_STRING_LEN];
41960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
42060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jstring implementor = env->NewStringUTF(nModules[i].properties.implementor);
42160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jstring description = env->NewStringUTF(nModules[i].properties.description);
42260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        SoundTrigger::guidToString(&nModules[i].properties.uuid,
42360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                   str,
42460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                   SOUND_TRIGGER_MAX_STRING_LEN);
42560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jstring uuid = env->NewStringUTF(str);
42660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
427d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        ALOGV("listModules module %zu id %d description %s maxSoundModels %d",
42860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent              i, nModules[i].handle, nModules[i].properties.description,
42960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent              nModules[i].properties.max_sound_models);
43060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
43160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jobject newModuleDesc = env->NewObject(gModulePropertiesClass, gModulePropertiesCstor,
43260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].handle,
43360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               implementor, description, uuid,
43460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].properties.version,
43560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].properties.max_sound_models,
43660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].properties.max_key_phrases,
43760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].properties.max_users,
43860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].properties.recognition_modes,
43960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].properties.capture_transition,
44060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].properties.max_buffer_ms,
44160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               nModules[i].properties.concurrent_capture,
442d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                               nModules[i].properties.power_consumption_mw,
443d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                               nModules[i].properties.trigger_in_event);
44460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
44560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->DeleteLocalRef(implementor);
44660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->DeleteLocalRef(description);
44760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->DeleteLocalRef(uuid);
44860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        if (newModuleDesc == NULL) {
44960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            status = SOUNDTRIGGER_STATUS_ERROR;
45060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            goto exit;
45160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
45260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->CallBooleanMethod(jModules, gArrayListMethods.add, newModuleDesc);
45360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
45460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
45560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentexit:
45660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    free(nModules);
45760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    return (jint) status;
45860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
45960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
46060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic void
46160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentandroid_hardware_SoundTrigger_setup(JNIEnv *env, jobject thiz, jobject weak_this)
46260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
46360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("setup");
46460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
46560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<JNISoundTriggerCallback> callback = new JNISoundTriggerCallback(env, thiz, weak_this);
46660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
46760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sound_trigger_module_handle_t handle =
46860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            (sound_trigger_module_handle_t)env->GetIntField(thiz, gModuleFields.mId);
46960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
47060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<SoundTrigger> module = SoundTrigger::attach(handle, callback);
47160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (module == 0) {
47260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return;
47360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
47460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
47560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    setSoundTrigger(env, thiz, module);
47660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
47760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
47860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic void
47960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentandroid_hardware_SoundTrigger_detach(JNIEnv *env, jobject thiz)
48060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
48160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("detach");
48260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<SoundTrigger> module = setSoundTrigger(env, thiz, 0);
48360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("detach module %p", module.get());
48460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (module != 0) {
48560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        ALOGV("detach module->detach()");
48660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        module->detach();
48760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
48860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
48960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
49060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic void
49160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentandroid_hardware_SoundTrigger_finalize(JNIEnv *env, jobject thiz)
49260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
49360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("finalize");
49460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
49560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (module != 0) {
49660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        ALOGW("SoundTrigger finalized without being detached");
49760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
49860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    android_hardware_SoundTrigger_detach(env, thiz);
49960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
50060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
50160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jint
50260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentandroid_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz,
50360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                             jobject jSoundModel, jintArray jHandle)
50460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
50560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jint status = SOUNDTRIGGER_STATUS_OK;
506013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jbyte *nData = NULL;
50760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    struct sound_trigger_sound_model *nSoundModel;
50860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jbyteArray jData;
50960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<MemoryDealer> memoryDealer;
51060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<IMemory> memory;
51160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    size_t size;
51260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sound_model_handle_t handle;
513d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    jobject jUuid;
514d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    jstring jUuidString;
515d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    const char *nUuidString;
51660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
51760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("loadSoundModel");
51860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
51960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (module == NULL) {
52060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_ERROR;
52160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
52260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (jHandle == NULL) {
52360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_BAD_VALUE;
52460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
52560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jsize jHandleLen = env->GetArrayLength(jHandle);
52660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (jHandleLen == 0) {
52760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_BAD_VALUE;
52860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
52960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jint *nHandle = env->GetIntArrayElements(jHandle, NULL);
53060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (nHandle == NULL) {
53160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_ERROR;
53260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
53360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (!env->IsInstanceOf(jSoundModel, gSoundModelClass)) {
53460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        status = SOUNDTRIGGER_STATUS_BAD_VALUE;
53560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        goto exit;
53660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
53760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    size_t offset;
53860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sound_trigger_sound_model_type_t type;
539d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    if (env->IsInstanceOf(jSoundModel, gKeyphraseSoundModelClass)) {
54060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        offset = sizeof(struct sound_trigger_phrase_sound_model);
54160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        type = SOUND_MODEL_TYPE_KEYPHRASE;
542ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta    } else if (env->IsInstanceOf(jSoundModel, gGenericSoundModelClass)) {
543ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta        offset = sizeof(struct sound_trigger_generic_sound_model);
544ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta        type = SOUND_MODEL_TYPE_GENERIC;
54560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    } else {
54660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        offset = sizeof(struct sound_trigger_sound_model);
54760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        type = SOUND_MODEL_TYPE_UNKNOWN;
54860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
549d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha
550d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    jUuid = env->GetObjectField(jSoundModel, gSoundModelFields.uuid);
551d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    jUuidString = (jstring)env->CallObjectMethod(jUuid, gUUIDMethods.toString);
552d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    nUuidString = env->GetStringUTFChars(jUuidString, NULL);
553d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    sound_trigger_uuid_t nUuid;
554d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    SoundTrigger::stringToGuid(nUuidString, &nUuid);
555d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    env->ReleaseStringUTFChars(jUuidString, nUuidString);
556d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    env->DeleteLocalRef(jUuidString);
557d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha
558d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    sound_trigger_uuid_t nVendorUuid;
559d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    jUuid = env->GetObjectField(jSoundModel, gSoundModelFields.vendorUuid);
560d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    if (jUuid != NULL) {
561d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        jUuidString = (jstring)env->CallObjectMethod(jUuid, gUUIDMethods.toString);
562d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        nUuidString = env->GetStringUTFChars(jUuidString, NULL);
563d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        SoundTrigger::stringToGuid(nUuidString, &nVendorUuid);
564d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        env->ReleaseStringUTFChars(jUuidString, nUuidString);
565d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        env->DeleteLocalRef(jUuidString);
566d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    } else {
567d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        SoundTrigger::stringToGuid("00000000-0000-0000-0000-000000000000", &nVendorUuid);
568d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    }
569d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
57060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jData = (jbyteArray)env->GetObjectField(jSoundModel, gSoundModelFields.data);
57160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (jData == NULL) {
57260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        status = SOUNDTRIGGER_STATUS_BAD_VALUE;
57360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        goto exit;
57460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
57560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    size = env->GetArrayLength(jData);
57660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
577013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    nData = env->GetByteArrayElements(jData, NULL);
57860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (jData == NULL) {
57960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        status = SOUNDTRIGGER_STATUS_ERROR;
58060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        goto exit;
58160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
58260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
58360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    memoryDealer = new MemoryDealer(offset + size, "SoundTrigge-JNI::LoadModel");
58460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (memoryDealer == 0) {
58560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        status = SOUNDTRIGGER_STATUS_ERROR;
58660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        goto exit;
58760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
58860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    memory = memoryDealer->allocate(offset + size);
58960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (memory == 0 || memory->pointer() == NULL) {
59060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        status = SOUNDTRIGGER_STATUS_ERROR;
59160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        goto exit;
59260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
59360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
59460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    nSoundModel = (struct sound_trigger_sound_model *)memory->pointer();
59560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
59660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    nSoundModel->type = type;
597d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha    nSoundModel->uuid = nUuid;
598d3b8223377b8046280e4c09e728edc600171f941Eric Laurent    nSoundModel->vendor_uuid = nVendorUuid;
59960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    nSoundModel->data_size = size;
60060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    nSoundModel->data_offset = offset;
60160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    memcpy((char *)nSoundModel + offset, nData, size);
60260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (type == SOUND_MODEL_TYPE_KEYPHRASE) {
60360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        struct sound_trigger_phrase_sound_model *phraseModel =
60460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                (struct sound_trigger_phrase_sound_model *)nSoundModel;
60560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
60660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        jobjectArray jPhrases =
607d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha            (jobjectArray)env->GetObjectField(jSoundModel, gKeyphraseSoundModelFields.keyphrases);
60860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        if (jPhrases == NULL) {
60960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            status = SOUNDTRIGGER_STATUS_BAD_VALUE;
61060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            goto exit;
61160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
61260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
61360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        size_t numPhrases = env->GetArrayLength(jPhrases);
61460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        phraseModel->num_phrases = numPhrases;
615d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        ALOGV("loadSoundModel numPhrases %zu", numPhrases);
61660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        for (size_t i = 0; i < numPhrases; i++) {
61760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
618d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha            phraseModel->phrases[i].id =
619d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                                    env->GetIntField(jPhrase,gKeyphraseFields.id);
62060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            phraseModel->phrases[i].recognition_mode =
621d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                                    env->GetIntField(jPhrase,gKeyphraseFields.recognitionModes);
622013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
623013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            jintArray jUsers = (jintArray)env->GetObjectField(jPhrase, gKeyphraseFields.users);
624013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            phraseModel->phrases[i].num_users = env->GetArrayLength(jUsers);
625013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            jint *nUsers = env->GetIntArrayElements(jUsers, NULL);
626013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            memcpy(phraseModel->phrases[i].users,
627013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                   nUsers,
628013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                   phraseModel->phrases[i].num_users * sizeof(int));
629013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            env->ReleaseIntArrayElements(jUsers, nUsers, 0);
630013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            env->DeleteLocalRef(jUsers);
631013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
632d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha            jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.locale);
63360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            const char *nLocale = env->GetStringUTFChars(jLocale, NULL);
63460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            strncpy(phraseModel->phrases[i].locale,
63560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                    nLocale,
63660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                    SOUND_TRIGGER_MAX_LOCALE_LEN);
637d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha            jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.text);
63860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            const char *nText = env->GetStringUTFChars(jText, NULL);
63960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            strncpy(phraseModel->phrases[i].text,
64060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                    nText,
64160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                    SOUND_TRIGGER_MAX_STRING_LEN);
64260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
64360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            env->ReleaseStringUTFChars(jLocale, nLocale);
64460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            env->DeleteLocalRef(jLocale);
64560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            env->ReleaseStringUTFChars(jText, nText);
64660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            env->DeleteLocalRef(jText);
647d3b8223377b8046280e4c09e728edc600171f941Eric Laurent            ALOGV("loadSoundModel phrases %zu text %s locale %s",
64860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                  i, phraseModel->phrases[i].text, phraseModel->phrases[i].locale);
649013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            env->DeleteLocalRef(jPhrase);
65060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
65160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->DeleteLocalRef(jPhrases);
652ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta    } else if (type == SOUND_MODEL_TYPE_GENERIC) {
653ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta        /* No initialization needed */
65460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
65560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    status = module->loadSoundModel(memory, &handle);
65660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("loadSoundModel status %d handle %d", status, handle);
65760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
65860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentexit:
65960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (nHandle != NULL) {
66060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        nHandle[0] = (jint)handle;
66160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        env->ReleaseIntArrayElements(jHandle, nHandle, NULL);
66260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
66360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (nData != NULL) {
664013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        env->ReleaseByteArrayElements(jData, nData, NULL);
66560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
66660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    return status;
66760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
66860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
66960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jint
67060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentandroid_hardware_SoundTrigger_unloadSoundModel(JNIEnv *env, jobject thiz,
67160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               jint jHandle)
67260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
67360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jint status = SOUNDTRIGGER_STATUS_OK;
67460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("unloadSoundModel");
67560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
67660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (module == NULL) {
67760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_ERROR;
67860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
67960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    status = module->unloadSoundModel((sound_model_handle_t)jHandle);
68060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
68160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    return status;
68260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
68360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
68460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jint
68560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentandroid_hardware_SoundTrigger_startRecognition(JNIEnv *env, jobject thiz,
686013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                               jint jHandle, jobject jConfig)
68760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
68860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jint status = SOUNDTRIGGER_STATUS_OK;
68960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("startRecognition");
69060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
69160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (module == NULL) {
69260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_ERROR;
69360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
694013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
695013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    if (!env->IsInstanceOf(jConfig, gRecognitionConfigClass)) {
696013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        return SOUNDTRIGGER_STATUS_BAD_VALUE;
697013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    }
698013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
699013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jbyteArray jData = (jbyteArray)env->GetObjectField(jConfig, gRecognitionConfigFields.data);
70060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jsize dataSize = 0;
701013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jbyte *nData = NULL;
70260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (jData != NULL) {
70360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        dataSize = env->GetArrayLength(jData);
70460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        if (dataSize == 0) {
70560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            return SOUNDTRIGGER_STATUS_BAD_VALUE;
70660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
707013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        nData = env->GetByteArrayElements(jData, NULL);
70860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        if (nData == NULL) {
70960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent            return SOUNDTRIGGER_STATUS_ERROR;
71060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
711013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    }
712013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
713013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    size_t totalSize = sizeof(struct sound_trigger_recognition_config) + dataSize;
714013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    sp<MemoryDealer> memoryDealer =
715013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            new MemoryDealer(totalSize, "SoundTrigge-JNI::StartRecognition");
716013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    if (memoryDealer == 0) {
717013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        return SOUNDTRIGGER_STATUS_ERROR;
718013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    }
719013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    sp<IMemory> memory = memoryDealer->allocate(totalSize);
720013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    if (memory == 0 || memory->pointer() == NULL) {
721013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        return SOUNDTRIGGER_STATUS_ERROR;
722013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    }
723013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    if (dataSize != 0) {
724013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        memcpy((char *)memory->pointer() + sizeof(struct sound_trigger_recognition_config),
725013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                nData,
726013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                dataSize);
727013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        env->ReleaseByteArrayElements(jData, nData, 0);
728013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    }
729013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    env->DeleteLocalRef(jData);
730013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    struct sound_trigger_recognition_config *config =
731013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                    (struct sound_trigger_recognition_config *)memory->pointer();
732013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    config->data_size = dataSize;
733013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    config->data_offset = sizeof(struct sound_trigger_recognition_config);
73489311c282abbbe647566ae4afbdb9c9851f0bec3Eric Laurent    config->capture_requested = env->GetBooleanField(jConfig,
735013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                 gRecognitionConfigFields.captureRequested);
736013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
737013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    config->num_phrases = 0;
738013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    jobjectArray jPhrases =
739013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        (jobjectArray)env->GetObjectField(jConfig, gRecognitionConfigFields.keyphrases);
740013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    if (jPhrases != NULL) {
741013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        config->num_phrases = env->GetArrayLength(jPhrases);
742013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    }
743013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    ALOGV("startRecognition num phrases %d", config->num_phrases);
744013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    for (size_t i = 0; i < config->num_phrases; i++) {
745013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
746013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        config->phrases[i].id = env->GetIntField(jPhrase,
747013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                gKeyphraseRecognitionExtraFields.id);
748013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        config->phrases[i].recognition_modes = env->GetIntField(jPhrase,
749013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                gKeyphraseRecognitionExtraFields.recognitionModes);
750d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        config->phrases[i].confidence_level = env->GetIntField(jPhrase,
751d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                            gKeyphraseRecognitionExtraFields.coarseConfidenceLevel);
752013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        config->phrases[i].num_levels = 0;
753013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        jobjectArray jConfidenceLevels = (jobjectArray)env->GetObjectField(jPhrase,
754013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                gKeyphraseRecognitionExtraFields.confidenceLevels);
755013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        if (jConfidenceLevels != NULL) {
756013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            config->phrases[i].num_levels = env->GetArrayLength(jConfidenceLevels);
75760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
758d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        ALOGV("startRecognition phrase %zu num_levels %d", i, config->phrases[i].num_levels);
759013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        for (size_t j = 0; j < config->phrases[i].num_levels; j++) {
760013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            jobject jConfidenceLevel = env->GetObjectArrayElement(jConfidenceLevels, j);
761013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            config->phrases[i].levels[j].user_id = env->GetIntField(jConfidenceLevel,
762013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                                    gConfidenceLevelFields.userId);
763013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            config->phrases[i].levels[j].level = env->GetIntField(jConfidenceLevel,
764013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                          gConfidenceLevelFields.confidenceLevel);
765013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent            env->DeleteLocalRef(jConfidenceLevel);
76660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        }
767d3b8223377b8046280e4c09e728edc600171f941Eric Laurent        ALOGV("startRecognition phrases %zu", i);
768013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        env->DeleteLocalRef(jConfidenceLevels);
769013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        env->DeleteLocalRef(jPhrase);
77060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
771013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent    env->DeleteLocalRef(jPhrases);
77260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
77360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    status = module->startRecognition(jHandle, memory);
77460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    return status;
77560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
77660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
77760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentstatic jint
77860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentandroid_hardware_SoundTrigger_stopRecognition(JNIEnv *env, jobject thiz,
77960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent                                               jint jHandle)
78060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
78160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    jint status = SOUNDTRIGGER_STATUS_OK;
78260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    ALOGV("stopRecognition");
78360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
78460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    if (module == NULL) {
78560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        return SOUNDTRIGGER_STATUS_ERROR;
78660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    }
78760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    status = module->stopRecognition(jHandle);
78860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    return status;
78960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
79060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
79176f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = {
79260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    {"listModules",
79360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        "(Ljava/util/ArrayList;)I",
79460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        (void *)android_hardware_SoundTrigger_listModules},
79560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent};
79660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
79760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
79876f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gModuleMethods[] = {
79960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    {"native_setup",
80060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        "(Ljava/lang/Object;)V",
80160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        (void *)android_hardware_SoundTrigger_setup},
80260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    {"native_finalize",
80360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        "()V",
80460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        (void *)android_hardware_SoundTrigger_finalize},
80560b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    {"detach",
80660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        "()V",
80760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        (void *)android_hardware_SoundTrigger_detach},
80860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    {"loadSoundModel",
80960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        "(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;[I)I",
81060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        (void *)android_hardware_SoundTrigger_loadSoundModel},
81160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    {"unloadSoundModel",
81260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        "(I)I",
81360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        (void *)android_hardware_SoundTrigger_unloadSoundModel},
81460b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    {"startRecognition",
815013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent        "(ILandroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I",
81660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        (void *)android_hardware_SoundTrigger_startRecognition},
81760b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent    {"stopRecognition",
81860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        "(I)I",
81960b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent        (void *)android_hardware_SoundTrigger_stopRecognition},
82060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent};
82160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
82260b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurentint register_android_hardware_SoundTrigger(JNIEnv *env)
82360b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent{
824ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
825ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
826ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
827ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
828ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass uuidClass = FindClassOrDie(env, "java/util/UUID");
829ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gUUIDClass = MakeGlobalRefOrDie(env, uuidClass);
830ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gUUIDMethods.toString = GetMethodIDOrDie(env, uuidClass, "toString", "()Ljava/lang/String;");
831ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
832ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass lClass = FindClassOrDie(env, kSoundTriggerClassPathName);
833ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gSoundTriggerClass = MakeGlobalRefOrDie(env, lClass);
834ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
835ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass moduleClass = FindClassOrDie(env, kModuleClassPathName);
836ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gModuleClass = MakeGlobalRefOrDie(env, moduleClass);
837ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gPostEventFromNative = GetStaticMethodIDOrDie(env, moduleClass, "postEventFromNative",
838ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                                  "(Ljava/lang/Object;IIILjava/lang/Object;)V");
839ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gModuleFields.mNativeContext = GetFieldIDOrDie(env, moduleClass, "mNativeContext", "J");
840ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gModuleFields.mId = GetFieldIDOrDie(env, moduleClass, "mId", "I");
841ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
842ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass modulePropertiesClass = FindClassOrDie(env, kModulePropertiesClassPathName);
843ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gModulePropertiesClass = MakeGlobalRefOrDie(env, modulePropertiesClass);
844ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gModulePropertiesCstor = GetMethodIDOrDie(env, modulePropertiesClass, "<init>",
845ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZIZ)V");
846ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
847ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass soundModelClass = FindClassOrDie(env, kSoundModelClassPathName);
848ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gSoundModelClass = MakeGlobalRefOrDie(env, soundModelClass);
849ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gSoundModelFields.uuid = GetFieldIDOrDie(env, soundModelClass, "uuid", "Ljava/util/UUID;");
850ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gSoundModelFields.vendorUuid = GetFieldIDOrDie(env, soundModelClass, "vendorUuid",
851ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                                   "Ljava/util/UUID;");
852ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gSoundModelFields.data = GetFieldIDOrDie(env, soundModelClass, "data", "[B");
853ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
854ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta    jclass genericSoundModelClass = FindClassOrDie(env, kGenericSoundModelClassPathName);
855ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta    gGenericSoundModelClass = MakeGlobalRefOrDie(env, genericSoundModelClass);
856ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta
857ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass keyphraseClass = FindClassOrDie(env, kKeyphraseClassPathName);
858ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseClass = MakeGlobalRefOrDie(env, keyphraseClass);
859ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseFields.id = GetFieldIDOrDie(env, keyphraseClass, "id", "I");
860ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseFields.recognitionModes = GetFieldIDOrDie(env, keyphraseClass, "recognitionModes",
861ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                                        "I");
862ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseFields.locale = GetFieldIDOrDie(env, keyphraseClass, "locale", "Ljava/lang/String;");
863ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseFields.text = GetFieldIDOrDie(env, keyphraseClass, "text", "Ljava/lang/String;");
864ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseFields.users = GetFieldIDOrDie(env, keyphraseClass, "users", "[I");
865ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
866ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass keyphraseSoundModelClass = FindClassOrDie(env, kKeyphraseSoundModelClassPathName);
867ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseSoundModelClass = MakeGlobalRefOrDie(env, keyphraseSoundModelClass);
868ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseSoundModelFields.keyphrases = GetFieldIDOrDie(env, keyphraseSoundModelClass,
869d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                                         "keyphrases",
870d4233c68fc17f0909e9e36494db85a634f8e2665Sandeep Siddhartha                                         "[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;");
87160b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
872ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass recognitionEventClass = FindClassOrDie(env, kRecognitionEventClassPathName);
873ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gRecognitionEventClass = MakeGlobalRefOrDie(env, recognitionEventClass);
874ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gRecognitionEventCstor = GetMethodIDOrDie(env, recognitionEventClass, "<init>",
875d3b8223377b8046280e4c09e728edc600171f941Eric Laurent                                              "(IIZIIIZLandroid/media/AudioFormat;[B)V");
87660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
877ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass keyphraseRecognitionEventClass = FindClassOrDie(env,
878ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                                           kKeyphraseRecognitionEventClassPathName);
879ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseRecognitionEventClass = MakeGlobalRefOrDie(env, keyphraseRecognitionEventClass);
880ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseRecognitionEventCstor = GetMethodIDOrDie(env, keyphraseRecognitionEventClass, "<init>",
881d3b8223377b8046280e4c09e728edc600171f941Eric Laurent              "(IIZIIIZLandroid/media/AudioFormat;[B[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V");
882013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
883ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta    jclass genericRecognitionEventClass = FindClassOrDie(env,
884ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta                                                           kGenericRecognitionEventClassPathName);
885ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta    gGenericRecognitionEventClass = MakeGlobalRefOrDie(env, genericRecognitionEventClass);
886ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta    gGenericRecognitionEventCstor = GetMethodIDOrDie(env, genericRecognitionEventClass, "<init>",
887ee3fc89a3a7b3a68ae0e9f6f9b8d0fe5e203a873Ryan Bavetta                                              "(IIZIIIZLandroid/media/AudioFormat;[B)V");
88860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
889ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass keyRecognitionConfigClass = FindClassOrDie(env, kRecognitionConfigClassPathName);
890ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gRecognitionConfigClass = MakeGlobalRefOrDie(env, keyRecognitionConfigClass);
891ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gRecognitionConfigFields.captureRequested = GetFieldIDOrDie(env, keyRecognitionConfigClass,
892ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                                                "captureRequested", "Z");
893ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gRecognitionConfigFields.keyphrases = GetFieldIDOrDie(env, keyRecognitionConfigClass,
894ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe           "keyphrases", "[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;");
895ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gRecognitionConfigFields.data = GetFieldIDOrDie(env, keyRecognitionConfigClass, "data", "[B");
896ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
897ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass keyphraseRecognitionExtraClass = FindClassOrDie(env,
898ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                                           kKeyphraseRecognitionExtraClassPathName);
899ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseRecognitionExtraClass = MakeGlobalRefOrDie(env, keyphraseRecognitionExtraClass);
900ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseRecognitionExtraCstor = GetMethodIDOrDie(env, keyphraseRecognitionExtraClass,
901ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            "<init>", "(III[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;)V");
902ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseRecognitionExtraFields.id = GetFieldIDOrDie(env, gKeyphraseRecognitionExtraClass,
903ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                                          "id", "I");
904ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseRecognitionExtraFields.recognitionModes = GetFieldIDOrDie(env,
905ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            gKeyphraseRecognitionExtraClass, "recognitionModes", "I");
906ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseRecognitionExtraFields.coarseConfidenceLevel = GetFieldIDOrDie(env,
907ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            gKeyphraseRecognitionExtraClass, "coarseConfidenceLevel", "I");
908ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gKeyphraseRecognitionExtraFields.confidenceLevels = GetFieldIDOrDie(env,
909ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            gKeyphraseRecognitionExtraClass, "confidenceLevels",
910ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            "[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;");
911ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
912ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass confidenceLevelClass = FindClassOrDie(env, kConfidenceLevelClassPathName);
913ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gConfidenceLevelClass = MakeGlobalRefOrDie(env, confidenceLevelClass);
914ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gConfidenceLevelCstor = GetMethodIDOrDie(env, confidenceLevelClass, "<init>", "(II)V");
915ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gConfidenceLevelFields.userId = GetFieldIDOrDie(env, confidenceLevelClass, "userId", "I");
916ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gConfidenceLevelFields.confidenceLevel = GetFieldIDOrDie(env, confidenceLevelClass,
917013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent                                                             "confidenceLevel", "I");
91860b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
919ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass audioFormatClass = FindClassOrDie(env, kAudioFormatClassPathName);
920ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
921a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung    gAudioFormatCstor = GetMethodIDOrDie(env, audioFormatClass, "<init>", "(IIII)V");
922d3b8223377b8046280e4c09e728edc600171f941Eric Laurent
923ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass soundModelEventClass = FindClassOrDie(env, kSoundModelEventClassPathName);
924ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gSoundModelEventClass = MakeGlobalRefOrDie(env, soundModelEventClass);
925ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gSoundModelEventCstor = GetMethodIDOrDie(env, soundModelEventClass, "<init>", "(II[B)V");
92660b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent
927013f66b92db609fceeff9c8171daca13d057cc95Eric Laurent
928ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    RegisterMethodsOrDie(env, kSoundTriggerClassPathName, gMethods, NELEM(gMethods));
929ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env, kModuleClassPathName, gModuleMethods, NELEM(gModuleMethods));
93060b62bc5c11c0bfcdf84ca8f5b2053e5747f86bcEric Laurent}
931