diff options
3 files changed, 288 insertions, 73 deletions
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java index 2d7af855fa10..f7636a35d8ef 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 class SoundTrigger { 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 class SoundTrigger { 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 @@ public class SoundTrigger { 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 @@ public class SoundTrigger { /***************************************************************************** * 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 @@ public class SoundTrigger { /** 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 @@ public class SoundTrigger { /** 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 @@ public class SoundTrigger { } /***************************************************************************** - * 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 @@ public class SoundTrigger { } /** - * 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 @@ public class SoundTrigger { /** 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 @@ public class SoundTrigger { /** * 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 69e991d261ab..afb92a124604 100644 --- a/core/jni/android_hardware_SoundTrigger.cpp +++ b/core/jni/android_hardware_SoundTrigger.cpp @@ -37,6 +37,11 @@ static struct { 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 @@ static const char* const kSoundModelClassPathName = "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 const char* const kRecognitionEventClassPathName = 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 @@ void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognitio (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 @@ void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognitio 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 @@ void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognitio 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 @@ android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz, 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 @@ android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz, } 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 @@ android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz, 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 @@ android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz, (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 @@ android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz, 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 @@ int register_android_hardware_SoundTrigger(JNIEnv *env) 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 @@ int register_android_hardware_SoundTrigger(JNIEnv *env) 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 @@ int register_android_hardware_SoundTrigger(JNIEnv *env) 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, diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java new file mode 100644 index 000000000000..cb902b29585b --- /dev/null +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java @@ -0,0 +1,181 @@ +/** + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.voiceinteraction; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDatabase.CursorFactory; +import android.database.sqlite.SQLiteOpenHelper; +import android.hardware.soundtrigger.SoundTrigger; +import android.hardware.soundtrigger.SoundTrigger.Keyphrase; +import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel; +import android.util.Slog; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * @hide + */ +public class DatabaseHelper extends SQLiteOpenHelper { + static final String TAG = "SoundModelDBHelper"; + + private static final String NAME = "sound_model.db"; + private static final int VERSION = 1; + + public static interface KeyphraseContract { + public static final String TABLE = "keyphrase"; + public static final String KEY_ID = "_id"; + public static final String KEY_RECOGNITION_MODES = "modes"; + public static final String KEY_LOCALE = "locale"; + public static final String KEY_HINT_TEXT = "hint_text"; + public static final String KEY_NUM_USERS = "num_users"; + public static final String KEY_SOUND_MODEL_ID = "sound_model_id"; + } + + public static interface SoundModelContract { + public static final String TABLE = "sound_model"; + public static final String KEY_ID = "_id"; + public static final String KEY_TYPE = "type"; + public static final String KEY_DATA = "data"; + } + + // Table Create Statements + private static final String CREATE_TABLE_KEYPRHASES = "CREATE TABLE " + + KeyphraseContract.TABLE + "(" + + KeyphraseContract.KEY_ID + " INTEGER PRIMARY KEY," + + KeyphraseContract.KEY_RECOGNITION_MODES + " INTEGER," + + KeyphraseContract.KEY_NUM_USERS + " INTEGER," + + KeyphraseContract.KEY_SOUND_MODEL_ID + " TEXT," + + KeyphraseContract.KEY_LOCALE + " TEXT," + + KeyphraseContract.KEY_HINT_TEXT + " TEXT" + ")"; + + private static final String CREATE_TABLE_SOUND_MODEL = "CREATE TABLE " + + SoundModelContract.TABLE + "(" + + SoundModelContract.KEY_ID + " TEXT PRIMARY KEY," + + SoundModelContract.KEY_TYPE + " INTEGER," + + SoundModelContract.KEY_DATA + " BLOB" + ")"; + + public DatabaseHelper(Context context, CursorFactory factory) { + super(context, NAME, null, VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + // creating required tables + db.execSQL(CREATE_TABLE_KEYPRHASES); + db.execSQL(CREATE_TABLE_SOUND_MODEL); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + // TODO(sansid): For now, drop older tables and recreate new ones. + db.execSQL("DROP TABLE IF EXISTS " + KeyphraseContract.TABLE); + db.execSQL("DROP TABLE IF EXISTS " + SoundModelContract.TABLE); + onCreate(db); + } + + /** + * TODO(sansid): Change to addOrUpdate to handle changes here. + */ + public void addKeyphraseSoundModel(KeyphraseSoundModel soundModel) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + // Generate a random ID for the model. + values.put(SoundModelContract.KEY_ID, soundModel.uuid.toString()); + values.put(SoundModelContract.KEY_DATA, soundModel.data); + values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE); + + if (db.insert(SoundModelContract.TABLE, null, values) != -1) { + for (Keyphrase keyphrase : soundModel.keyphrases) { + addKeyphrase(soundModel.uuid, keyphrase); + } + } else { + Slog.w(TAG, "Failed to persist sound model to database"); + } + } + + /** + * TODO(sansid): Change to addOrUpdate to handle changes here. + */ + private void addKeyphrase(UUID modelId, SoundTrigger.Keyphrase keyphrase) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(KeyphraseContract.KEY_ID, keyphrase.id); + values.put(KeyphraseContract.KEY_RECOGNITION_MODES, keyphrase.recognitionModes); + values.put(KeyphraseContract.KEY_SOUND_MODEL_ID, keyphrase.id); + values.put(KeyphraseContract.KEY_HINT_TEXT, keyphrase.text); + values.put(KeyphraseContract.KEY_LOCALE, keyphrase.locale); + if (db.insert(KeyphraseContract.TABLE, null, values) == -1) { + Slog.w(TAG, "Failed to persist keyphrase to database"); + } + } + + /** + * Lists all the keyphrase sound models currently registered with the system. + */ + public List<KeyphraseSoundModel> getKephraseSoundModels() { + List<KeyphraseSoundModel> models = new ArrayList<>(); + String selectQuery = "SELECT * FROM " + SoundModelContract.TABLE; + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = db.rawQuery(selectQuery, null); + + // looping through all rows and adding to list + if (c.moveToFirst()) { + do { + int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE)); + if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) { + // Ignore non-keyphrase sound models. + continue; + } + String id = c.getString(c.getColumnIndex(SoundModelContract.KEY_ID)); + byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA)); + // Get all the keyphrases for this this sound model. + models.add(new KeyphraseSoundModel( + UUID.fromString(id), data, getKeyphrasesForSoundModel(id))); + } while (c.moveToNext()); + } + return models; + } + + private Keyphrase[] getKeyphrasesForSoundModel(String modelId) { + List<Keyphrase> keyphrases = new ArrayList<>(); + String selectQuery = "SELECT * FROM " + KeyphraseContract.TABLE + + " WHERE " + KeyphraseContract.KEY_SOUND_MODEL_ID + " = '" + modelId + "'"; + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = db.rawQuery(selectQuery, null); + + // looping through all rows and adding to list + if (c.moveToFirst()) { + do { + int id = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_ID)); + int modes = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_RECOGNITION_MODES)); + int numUsers = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_NUM_USERS)); + String locale = c.getString(c.getColumnIndex(KeyphraseContract.KEY_LOCALE)); + String hintText = c.getString(c.getColumnIndex(KeyphraseContract.KEY_HINT_TEXT)); + + keyphrases.add(new Keyphrase(id, modes, locale, hintText, numUsers)); + } while (c.moveToNext()); + } + Keyphrase[] keyphraseArr = new Keyphrase[keyphrases.size()]; + keyphrases.toArray(keyphraseArr); + return keyphraseArr; + } +} |