import java.util.Locale;
import java.util.UUID;
+import java.util.List;
+import java.util.ArrayList;
/**
* Helper to manage the database of the sound models that have been registered on the device.
static final boolean DBG = false;
private static final String NAME = "sound_model.db";
- private static final int VERSION = 5;
+ private static final int VERSION = 6;
public static interface SoundModelContract {
public static final String TABLE = "sound_model";
// Table Create Statement
private static final String CREATE_TABLE_SOUND_MODEL = "CREATE TABLE "
+ SoundModelContract.TABLE + "("
- + SoundModelContract.KEY_MODEL_UUID + " TEXT PRIMARY KEY,"
- + SoundModelContract.KEY_VENDOR_UUID + " TEXT, "
+ + SoundModelContract.KEY_MODEL_UUID + " TEXT,"
+ + SoundModelContract.KEY_VENDOR_UUID + " TEXT,"
+ SoundModelContract.KEY_KEYPHRASE_ID + " INTEGER,"
+ SoundModelContract.KEY_TYPE + " INTEGER,"
+ SoundModelContract.KEY_DATA + " BLOB,"
+ SoundModelContract.KEY_RECOGNITION_MODES + " INTEGER,"
+ SoundModelContract.KEY_LOCALE + " TEXT,"
+ SoundModelContract.KEY_HINT_TEXT + " TEXT,"
- + SoundModelContract.KEY_USERS + " TEXT" + ")";
+ + SoundModelContract.KEY_USERS + " TEXT,"
+ + "PRIMARY KEY (" + SoundModelContract.KEY_KEYPHRASE_ID + ","
+ + SoundModelContract.KEY_LOCALE + ","
+ + SoundModelContract.KEY_USERS + ")"
+ + ")";
public DatabaseHelper(Context context) {
super(context, NAME, null, VERSION);
oldVersion++;
}
}
+ if (oldVersion == 5) {
+ // We need to enforce the new primary key constraint that the
+ // keyphrase id, locale, and users are unique. We have to first pull
+ // everything out of the database, remove duplicates, create the new
+ // table, then push everything back in.
+ String selectQuery = "SELECT * FROM " + SoundModelContract.TABLE;
+ Cursor c = db.rawQuery(selectQuery, null);
+ List<SoundModelRecord> old_records = new ArrayList<SoundModelRecord>();
+ try {
+ if (c.moveToFirst()) {
+ do {
+ try {
+ old_records.add(new SoundModelRecord(5, c));
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to extract V5 record", e);
+ }
+ } while (c.moveToNext());
+ }
+ } finally {
+ c.close();
+ }
+ db.execSQL("DROP TABLE IF EXISTS " + SoundModelContract.TABLE);
+ onCreate(db);
+ for (SoundModelRecord record : old_records) {
+ if (!record.violatesV6PrimaryKeyConstraint(old_records)) {
+ try {
+ long return_value = record.writeToDatabase(6, db);
+ if (return_value == -1) {
+ Slog.e(TAG, "Database write failed " + record.modelUuid + ": "
+ + return_value);
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to update V6 record " + record.modelUuid, e);
+ }
+ }
+ }
+ oldVersion++;
+ }
}
/**
}
return users;
}
+
+ private static class SoundModelRecord {
+ public final String modelUuid;
+ public final String vendorUuid;
+ public final int keyphraseId;
+ public final int type;
+ public final byte[] data;
+ public final int recognitionModes;
+ public final String locale;
+ public final String hintText;
+ public final String users;
+
+ public SoundModelRecord(int version, Cursor c) {
+ modelUuid = c.getString(c.getColumnIndex(SoundModelContract.KEY_MODEL_UUID));
+ if (version >= 5) {
+ vendorUuid = c.getString(c.getColumnIndex(SoundModelContract.KEY_VENDOR_UUID));
+ } else {
+ vendorUuid = null;
+ }
+ keyphraseId = c.getInt(c.getColumnIndex(SoundModelContract.KEY_KEYPHRASE_ID));
+ type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
+ data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
+ recognitionModes = c.getInt(c.getColumnIndex(SoundModelContract.KEY_RECOGNITION_MODES));
+ locale = c.getString(c.getColumnIndex(SoundModelContract.KEY_LOCALE));
+ hintText = c.getString(c.getColumnIndex(SoundModelContract.KEY_HINT_TEXT));
+ users = c.getString(c.getColumnIndex(SoundModelContract.KEY_USERS));
+ }
+
+ // Check to see if this record conflicts with some other record in the list of records.
+ public boolean violatesV6PrimaryKeyConstraint(List<SoundModelRecord> records) {
+ for (SoundModelRecord record : records) {
+ if (this == record) {
+ continue;
+ }
+ if (keyphraseId == record.keyphraseId
+ && stringComparisonHelper(locale, record.locale)
+ && stringComparisonHelper(users, record.users)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public long writeToDatabase(int version, SQLiteDatabase db) {
+ ContentValues values = new ContentValues();
+ values.put(SoundModelContract.KEY_MODEL_UUID, modelUuid);
+ if (version >= 5) {
+ values.put(SoundModelContract.KEY_VENDOR_UUID, vendorUuid);
+ }
+ values.put(SoundModelContract.KEY_KEYPHRASE_ID, keyphraseId);
+ values.put(SoundModelContract.KEY_TYPE, type);
+ values.put(SoundModelContract.KEY_DATA, data);
+ values.put(SoundModelContract.KEY_RECOGNITION_MODES, recognitionModes);
+ values.put(SoundModelContract.KEY_LOCALE, locale);
+ values.put(SoundModelContract.KEY_HINT_TEXT, hintText);
+ values.put(SoundModelContract.KEY_USERS, users);
+
+ return db.insertWithOnConflict(
+ SoundModelContract.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
+ }
+
+ // Helper for checking string equality - including the case when they are null.
+ static private boolean stringComparisonHelper(String a, String b) {
+ if (a != null) {
+ return a.equals(b);
+ }
+ return a == b;
+ }
+ }
}