Initial code for listing/storing sound models
- We use a DB to store and persist the sound models.
- This'll be used by SoundTriggerModelManager, a service that lists,
deletes and registers new models. This'll be used by the enrollment
client to enroll and unenroll users.
- This needs the unique identifiers for sound model & keyphrases to be
present in the respective data structures
This is very early stage so please point out any concerns.
Change-Id: I82962895bf326167458f20e6ba995295551de025
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 2d7af85..f7636a3 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -16,8 +16,6 @@
package android.hardware.soundtrigger;
-import android.content.Context;
-import android.content.Intent;
import android.os.Handler;
import java.util.ArrayList;
@@ -65,7 +63,7 @@
public final int maxSoundModels;
/** Maximum number of key phrases */
- public final int maxKeyPhrases;
+ public final int maxKeyphrases;
/** Maximum number of users per key phrase */
public final int maxUsers;
@@ -86,7 +84,7 @@
public final int powerConsumptionMw;
ModuleProperties(int id, String implementor, String description,
- String uuid, int version, int maxSoundModels, int maxKeyPhrases,
+ String uuid, int version, int maxSoundModels, int maxKeyphrases,
int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
int maxBufferMs, boolean supportsConcurrentCapture,
int powerConsumptionMw) {
@@ -96,7 +94,7 @@
this.uuid = UUID.fromString(uuid);
this.version = version;
this.maxSoundModels = maxSoundModels;
- this.maxKeyPhrases = maxKeyPhrases;
+ this.maxKeyphrases = maxKeyphrases;
this.maxUsers = maxUsers;
this.recognitionModes = recognitionModes;
this.supportsCaptureTransition = supportsCaptureTransition;
@@ -109,7 +107,7 @@
/*****************************************************************************
* A SoundModel describes the attributes and contains the binary data used by the hardware
* implementation to detect a particular sound pattern.
- * A specialized version {@link KeyPhraseSoundModel} is defined for key phrase
+ * A specialized version {@link KeyphraseSoundModel} is defined for key phrase
* sound models.
****************************************************************************/
public static class SoundModel {
@@ -119,23 +117,30 @@
/** Keyphrase sound model */
public static final int TYPE_KEYPHRASE = 0;
+ /** Unique sound model identifier */
+ public final UUID uuid;
+
/** Sound model type (e.g. TYPE_KEYPHRASE); */
public final int type;
/** Opaque data. For use by vendor implementation and enrollment application */
public final byte[] data;
- public SoundModel(int type, byte[] data) {
+ public SoundModel(UUID uuid, int type, byte[] data) {
+ this.uuid = uuid;
this.type = type;
this.data = data;
}
}
/*****************************************************************************
- * A KeyPhrase describes a key phrase that can be detected by a
- * {@link KeyPhraseSoundModel}
+ * A Keyphrase describes a key phrase that can be detected by a
+ * {@link KeyphraseSoundModel}
****************************************************************************/
- public static class KeyPhrase {
+ public static class Keyphrase {
+ /** Unique identifier for this keyphrase */
+ public final int id;
+
/** Recognition modes supported for this key phrase in the model */
public final int recognitionModes;
@@ -148,7 +153,8 @@
/** Number of users this key phrase has been trained for */
public final int numUsers;
- public KeyPhrase(int recognitionModes, String locale, String text, int numUsers) {
+ public Keyphrase(int id, int recognitionModes, String locale, String text, int numUsers) {
+ this.id = id;
this.recognitionModes = recognitionModes;
this.locale = locale;
this.text = text;
@@ -157,17 +163,17 @@
}
/*****************************************************************************
- * A KeyPhraseSoundModel is a specialized {@link SoundModel} for key phrases.
+ * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases.
* It contains data needed by the hardware to detect a certain number of key phrases
- * and the list of corresponding {@link KeyPhrase} descriptors.
+ * and the list of corresponding {@link Keyphrase} descriptors.
****************************************************************************/
- public static class KeyPhraseSoundModel extends SoundModel {
+ public static class KeyphraseSoundModel extends SoundModel {
/** Key phrases in this sound model */
- public final KeyPhrase[] keyPhrases; // keyword phrases in model
+ public final Keyphrase[] keyphrases; // keyword phrases in model
- public KeyPhraseSoundModel(byte[] data, KeyPhrase[] keyPhrases) {
- super(TYPE_KEYPHRASE, data);
- this.keyPhrases = keyPhrases;
+ public KeyphraseSoundModel(UUID id, byte[] data, Keyphrase[] keyphrases) {
+ super(id, TYPE_KEYPHRASE, data);
+ this.keyphrases = keyphrases;
}
}
@@ -225,10 +231,10 @@
}
/**
- * Additional data conveyed by a {@link KeyPhraseRecognitionEvent}
+ * Additional data conveyed by a {@link KeyphraseRecognitionEvent}
* for a key phrase detection.
*/
- public static class KeyPhraseRecognitionExtra {
+ public static class KeyphraseRecognitionExtra {
/** Confidence level for each user defined in the key phrase in the same order as
* users in the key phrase. The confidence level is expressed in percentage (0% -100%) */
public final int[] confidenceLevels;
@@ -236,7 +242,7 @@
/** Recognition modes matched for this event */
public final int recognitionModes;
- KeyPhraseRecognitionExtra(int[] confidenceLevels, int recognitionModes) {
+ KeyphraseRecognitionExtra(int[] confidenceLevels, int recognitionModes) {
this.confidenceLevels = confidenceLevels;
this.recognitionModes = recognitionModes;
}
@@ -245,19 +251,19 @@
/**
* Specialized {@link RecognitionEvent} for a key phrase detection.
*/
- public static class KeyPhraseRecognitionEvent extends RecognitionEvent {
+ public static class KeyphraseRecognitionEvent extends RecognitionEvent {
/** Indicates if the key phrase is present in the buffered audio available for capture */
- public final KeyPhraseRecognitionExtra[] keyPhraseExtras;
+ public final KeyphraseRecognitionExtra[] keyphraseExtras;
/** Additional data available for each recognized key phrases in the model */
- public final boolean keyPhraseInCapture;
+ public final boolean keyphraseInCapture;
- KeyPhraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
+ KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
int captureSession, int captureDelayMs, byte[] data,
- boolean keyPhraseInCapture, KeyPhraseRecognitionExtra[] keyPhraseExtras) {
+ boolean keyphraseInCapture, KeyphraseRecognitionExtra[] keyphraseExtras) {
super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs, data);
- this.keyPhraseInCapture = keyPhraseInCapture;
- this.keyPhraseExtras = keyPhraseExtras;
+ this.keyphraseInCapture = keyphraseInCapture;
+ this.keyphraseExtras = keyphraseExtras;
}
}
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 69e991d..afb92a1 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -37,6 +37,11 @@
jmethodID add;
} gArrayListMethods;
+static jclass gUUIDClass;
+static struct {
+ jmethodID toString;
+} gUUIDMethods;
+
static const char* const kSoundTriggerClassPathName = "android/hardware/soundtrigger/SoundTrigger";
static jclass gSoundTriggerClass;
@@ -57,25 +62,27 @@
"android/hardware/soundtrigger/SoundTrigger$SoundModel";
static jclass gSoundModelClass;
static struct {
+ jfieldID uuid;
jfieldID data;
} gSoundModelFields;
-static const char* const kKeyPhraseClassPathName =
- "android/hardware/soundtrigger/SoundTrigger$KeyPhrase";
-static jclass gKeyPhraseClass;
+static const char* const kKeyphraseClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$Keyphrase";
+static jclass gKeyphraseClass;
static struct {
+ jfieldID id;
jfieldID recognitionModes;
jfieldID locale;
jfieldID text;
jfieldID numUsers;
-} gKeyPhraseFields;
+} gKeyphraseFields;
-static const char* const kKeyPhraseSoundModelClassPathName =
- "android/hardware/soundtrigger/SoundTrigger$KeyPhraseSoundModel";
-static jclass gKeyPhraseSoundModelClass;
+static const char* const kKeyphraseSoundModelClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel";
+static jclass gKeyphraseSoundModelClass;
static struct {
- jfieldID keyPhrases;
-} gKeyPhraseSoundModelFields;
+ jfieldID keyphrases;
+} gKeyphraseSoundModelFields;
static const char* const kRecognitionEventClassPathName =
@@ -83,15 +90,15 @@
static jclass gRecognitionEventClass;
static jmethodID gRecognitionEventCstor;
-static const char* const kKeyPhraseRecognitionEventClassPathName =
- "android/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionEvent";
-static jclass gKeyPhraseRecognitionEventClass;
-static jmethodID gKeyPhraseRecognitionEventCstor;
+static const char* const kKeyphraseRecognitionEventClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent";
+static jclass gKeyphraseRecognitionEventClass;
+static jmethodID gKeyphraseRecognitionEventCstor;
-static const char* const kKeyPhraseRecognitionExtraClassPathName =
- "android/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionExtra";
-static jclass gKeyPhraseRecognitionExtraClass;
-static jmethodID gKeyPhraseRecognitionExtraCstor;
+static const char* const kKeyphraseRecognitionExtraClassPathName =
+ "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra";
+static jclass gKeyphraseRecognitionExtraClass;
+static jmethodID gKeyphraseRecognitionExtraCstor;
static Mutex gLock;
@@ -170,7 +177,7 @@
(struct sound_trigger_phrase_recognition_event *)event;
jobjectArray jExtras = env->NewObjectArray(phraseEvent->num_phrases,
- gKeyPhraseRecognitionExtraClass, NULL);
+ gKeyphraseRecognitionExtraClass, NULL);
if (jExtras == NULL) {
return;
}
@@ -185,8 +192,8 @@
phraseEvent->phrase_extras[i].confidence_levels,
phraseEvent->phrase_extras[i].num_users * sizeof(int));
env->ReleaseIntArrayElements(jConfidenceLevels, nConfidenceLevels, 0);
- jobject jNewExtra = env->NewObject(gKeyPhraseRecognitionExtraClass,
- gKeyPhraseRecognitionExtraCstor,
+ jobject jNewExtra = env->NewObject(gKeyphraseRecognitionExtraClass,
+ gKeyphraseRecognitionExtraCstor,
jConfidenceLevels,
phraseEvent->phrase_extras[i].recognition_modes);
@@ -196,7 +203,7 @@
env->SetObjectArrayElement(jExtras, i, jNewExtra);
}
- jEvent = env->NewObject(gKeyPhraseRecognitionEventClass, gKeyPhraseRecognitionEventCstor,
+ jEvent = env->NewObject(gKeyphraseRecognitionEventClass, gKeyphraseRecognitionEventCstor,
event->status, event->model, event->capture_available,
event->capture_session, event->capture_delay_ms, jData,
phraseEvent->key_phrase_in_capture, jExtras);
@@ -381,6 +388,9 @@
sp<IMemory> memory;
size_t size;
sound_model_handle_t handle;
+ jobject jUuid;
+ jstring jUuidString;
+ const char *nUuidString;
ALOGV("loadSoundModel");
sp<SoundTrigger> module = getSoundTrigger(env, thiz);
@@ -404,13 +414,22 @@
}
size_t offset;
sound_trigger_sound_model_type_t type;
- if (env->IsInstanceOf(jSoundModel, gKeyPhraseSoundModelClass)) {
+ if (env->IsInstanceOf(jSoundModel, gKeyphraseSoundModelClass)) {
offset = sizeof(struct sound_trigger_phrase_sound_model);
type = SOUND_MODEL_TYPE_KEYPHRASE;
} else {
offset = sizeof(struct sound_trigger_sound_model);
type = SOUND_MODEL_TYPE_UNKNOWN;
}
+
+ jUuid = env->GetObjectField(jSoundModel, gSoundModelFields.uuid);
+ jUuidString = (jstring)env->CallObjectMethod(jUuid, gUUIDMethods.toString);
+ nUuidString = env->GetStringUTFChars(jUuidString, NULL);
+ sound_trigger_uuid_t nUuid;
+ SoundTrigger::stringToGuid(nUuidString, &nUuid);
+ env->ReleaseStringUTFChars(jUuidString, nUuidString);
+ env->DeleteLocalRef(jUuidString);
+
jData = (jbyteArray)env->GetObjectField(jSoundModel, gSoundModelFields.data);
if (jData == NULL) {
status = SOUNDTRIGGER_STATUS_BAD_VALUE;
@@ -438,6 +457,7 @@
nSoundModel = (struct sound_trigger_sound_model *)memory->pointer();
nSoundModel->type = type;
+ nSoundModel->uuid = nUuid;
nSoundModel->data_size = size;
nSoundModel->data_offset = offset;
memcpy((char *)nSoundModel + offset, nData, size);
@@ -446,7 +466,7 @@
(struct sound_trigger_phrase_sound_model *)nSoundModel;
jobjectArray jPhrases =
- (jobjectArray)env->GetObjectField(jSoundModel, gKeyPhraseSoundModelFields.keyPhrases);
+ (jobjectArray)env->GetObjectField(jSoundModel, gKeyphraseSoundModelFields.keyphrases);
if (jPhrases == NULL) {
status = SOUNDTRIGGER_STATUS_BAD_VALUE;
goto exit;
@@ -457,16 +477,18 @@
ALOGV("loadSoundModel numPhrases %d", numPhrases);
for (size_t i = 0; i < numPhrases; i++) {
jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
+ phraseModel->phrases[i].id =
+ env->GetIntField(jPhrase,gKeyphraseFields.id);
phraseModel->phrases[i].recognition_mode =
- env->GetIntField(jPhrase,gKeyPhraseFields.recognitionModes);
+ env->GetIntField(jPhrase,gKeyphraseFields.recognitionModes);
phraseModel->phrases[i].num_users =
- env->GetIntField(jPhrase, gKeyPhraseFields.numUsers);
- jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyPhraseFields.locale);
+ env->GetIntField(jPhrase, gKeyphraseFields.numUsers);
+ jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.locale);
const char *nLocale = env->GetStringUTFChars(jLocale, NULL);
strncpy(phraseModel->phrases[i].locale,
nLocale,
SOUND_TRIGGER_MAX_LOCALE_LEN);
- jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyPhraseFields.text);
+ jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.text);
const char *nText = env->GetStringUTFChars(jText, NULL);
strncpy(phraseModel->phrases[i].text,
nText,
@@ -599,6 +621,10 @@
gArrayListClass = (jclass) env->NewGlobalRef(arrayListClass);
gArrayListMethods.add = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
+ jclass uuidClass = env->FindClass("java/util/UUID");
+ gUUIDClass = (jclass) env->NewGlobalRef(uuidClass);
+ gUUIDMethods.toString = env->GetMethodID(uuidClass, "toString", "()Ljava/lang/String;");
+
jclass lClass = env->FindClass(kSoundTriggerClassPathName);
gSoundTriggerClass = (jclass) env->NewGlobalRef(lClass);
@@ -617,20 +643,22 @@
jclass soundModelClass = env->FindClass(kSoundModelClassPathName);
gSoundModelClass = (jclass) env->NewGlobalRef(soundModelClass);
+ gSoundModelFields.uuid = env->GetFieldID(soundModelClass, "uuid", "Ljava/util/UUID;");
gSoundModelFields.data = env->GetFieldID(soundModelClass, "data", "[B");
- jclass keyPhraseClass = env->FindClass(kKeyPhraseClassPathName);
- gKeyPhraseClass = (jclass) env->NewGlobalRef(keyPhraseClass);
- gKeyPhraseFields.recognitionModes = env->GetFieldID(keyPhraseClass, "recognitionModes", "I");
- gKeyPhraseFields.locale = env->GetFieldID(keyPhraseClass, "locale", "Ljava/lang/String;");
- gKeyPhraseFields.text = env->GetFieldID(keyPhraseClass, "text", "Ljava/lang/String;");
- gKeyPhraseFields.numUsers = env->GetFieldID(keyPhraseClass, "numUsers", "I");
+ jclass keyphraseClass = env->FindClass(kKeyphraseClassPathName);
+ gKeyphraseClass = (jclass) env->NewGlobalRef(keyphraseClass);
+ gKeyphraseFields.id = env->GetFieldID(keyphraseClass, "id", "I");
+ gKeyphraseFields.recognitionModes = env->GetFieldID(keyphraseClass, "recognitionModes", "I");
+ gKeyphraseFields.locale = env->GetFieldID(keyphraseClass, "locale", "Ljava/lang/String;");
+ gKeyphraseFields.text = env->GetFieldID(keyphraseClass, "text", "Ljava/lang/String;");
+ gKeyphraseFields.numUsers = env->GetFieldID(keyphraseClass, "numUsers", "I");
- jclass keyPhraseSoundModelClass = env->FindClass(kKeyPhraseSoundModelClassPathName);
- gKeyPhraseSoundModelClass = (jclass) env->NewGlobalRef(keyPhraseSoundModelClass);
- gKeyPhraseSoundModelFields.keyPhrases = env->GetFieldID(keyPhraseSoundModelClass,
- "keyPhrases",
- "[Landroid/hardware/soundtrigger/SoundTrigger$KeyPhrase;");
+ jclass keyphraseSoundModelClass = env->FindClass(kKeyphraseSoundModelClassPathName);
+ gKeyphraseSoundModelClass = (jclass) env->NewGlobalRef(keyphraseSoundModelClass);
+ gKeyphraseSoundModelFields.keyphrases = env->GetFieldID(keyphraseSoundModelClass,
+ "keyphrases",
+ "[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;");
jclass recognitionEventClass = env->FindClass(kRecognitionEventClassPathName);
@@ -638,15 +666,15 @@
gRecognitionEventCstor = env->GetMethodID(recognitionEventClass, "<init>",
"(IIZII[B)V");
- jclass keyPhraseRecognitionEventClass = env->FindClass(kKeyPhraseRecognitionEventClassPathName);
- gKeyPhraseRecognitionEventClass = (jclass) env->NewGlobalRef(keyPhraseRecognitionEventClass);
- gKeyPhraseRecognitionEventCstor = env->GetMethodID(keyPhraseRecognitionEventClass, "<init>",
- "(IIZII[BZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionExtra;)V");
+ jclass keyphraseRecognitionEventClass = env->FindClass(kKeyphraseRecognitionEventClassPathName);
+ gKeyphraseRecognitionEventClass = (jclass) env->NewGlobalRef(keyphraseRecognitionEventClass);
+ gKeyphraseRecognitionEventCstor = env->GetMethodID(keyphraseRecognitionEventClass, "<init>",
+ "(IIZII[BZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V");
- jclass keyPhraseRecognitionExtraClass = env->FindClass(kKeyPhraseRecognitionExtraClassPathName);
- gKeyPhraseRecognitionExtraClass = (jclass) env->NewGlobalRef(keyPhraseRecognitionExtraClass);
- gKeyPhraseRecognitionExtraCstor = env->GetMethodID(keyPhraseRecognitionExtraClass, "<init>",
+ jclass keyphraseRecognitionExtraClass = env->FindClass(kKeyphraseRecognitionExtraClassPathName);
+ gKeyphraseRecognitionExtraClass = (jclass) env->NewGlobalRef(keyphraseRecognitionExtraClass);
+ gKeyphraseRecognitionExtraCstor = env->GetMethodID(keyphraseRecognitionExtraClass, "<init>",
"([II)V");
int status = AndroidRuntime::registerNativeMethods(env,