1a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra/** 2a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Copyright (C) 2014 The Android Open Source Project 3a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 4a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Licensed under the Apache License, Version 2.0 (the "License"); 5a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * you may not use this file except in compliance with the License. 6a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * You may obtain a copy of the License at 7a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 8a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * http://www.apache.org/licenses/LICENSE-2.0 9a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 10a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Unless required by applicable law or agreed to in writing, software 11a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * distributed under the License is distributed on an "AS IS" BASIS, 12a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * See the License for the specific language governing permissions and 14a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * limitations under the License. 15a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra */ 16a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 17a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishrapackage com.android.server.soundtrigger; 18a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 19a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.content.ContentValues; 20a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.content.Context; 21a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.database.Cursor; 22a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.database.sqlite.SQLiteDatabase; 23a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.database.sqlite.SQLiteOpenHelper; 24a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.hardware.soundtrigger.SoundTrigger; 25a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.hardware.soundtrigger.SoundTrigger.GenericSoundModel; 26a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.text.TextUtils; 27a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.util.Slog; 28a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 29a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport java.util.Locale; 30a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport java.util.UUID; 31a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 32a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra/** 33a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Helper to manage the database of the sound models that have been registered on the device. 34a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 35a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * @hide 36a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra */ 37a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishrapublic class SoundTriggerDbHelper extends SQLiteOpenHelper { 38a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra static final String TAG = "SoundTriggerDbHelper"; 39a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra static final boolean DBG = false; 40a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 41a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private static final String NAME = "st_sound_model.db"; 42a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private static final int VERSION = 1; 43a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 44a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra // Sound trigger-based sound models. 45a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public static interface GenericSoundModelContract { 46a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public static final String TABLE = "st_sound_model"; 47a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public static final String KEY_MODEL_UUID = "model_uuid"; 48a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public static final String KEY_VENDOR_UUID = "vendor_uuid"; 49a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public static final String KEY_DATA = "data"; 50a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 51a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 52a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 53a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra // Table Create Statement for the sound trigger table 54a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private static final String CREATE_TABLE_ST_SOUND_MODEL = "CREATE TABLE " 55a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra + GenericSoundModelContract.TABLE + "(" 56a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra + GenericSoundModelContract.KEY_MODEL_UUID + " TEXT PRIMARY KEY," 573fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra + GenericSoundModelContract.KEY_VENDOR_UUID + " TEXT," 58a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra + GenericSoundModelContract.KEY_DATA + " BLOB" + " )"; 59a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 60a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 61a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public SoundTriggerDbHelper(Context context) { 62a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra super(context, NAME, null, VERSION); 63a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 64a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 65a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 66a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public void onCreate(SQLiteDatabase db) { 67a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra // creating required tables 68a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra db.execSQL(CREATE_TABLE_ST_SOUND_MODEL); 69a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 70a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 71a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 72a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 73a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra // TODO: For now, drop older tables and recreate new ones. 74a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra db.execSQL("DROP TABLE IF EXISTS " + GenericSoundModelContract.TABLE); 75a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra onCreate(db); 76a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 77a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 78a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra /** 79a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Updates the given sound trigger model, adds it, if it doesn't already exist. 80a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 81a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra */ 82a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public boolean updateGenericSoundModel(GenericSoundModel soundModel) { 83a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra synchronized(this) { 84a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra SQLiteDatabase db = getWritableDatabase(); 85a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra ContentValues values = new ContentValues(); 86a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.uuid.toString()); 87a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra values.put(GenericSoundModelContract.KEY_VENDOR_UUID, soundModel.vendorUuid.toString()); 88a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra values.put(GenericSoundModelContract.KEY_DATA, soundModel.data); 89a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 90a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra try { 91a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra return db.insertWithOnConflict(GenericSoundModelContract.TABLE, null, values, 92a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra SQLiteDatabase.CONFLICT_REPLACE) != -1; 93a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } finally { 94a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra db.close(); 95a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 96a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 97a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 98a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 99a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 100a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public GenericSoundModel getGenericSoundModel(UUID model_uuid) { 101a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra synchronized(this) { 102a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 103a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra // Find the corresponding sound model ID for the keyphrase. 104a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra String selectQuery = "SELECT * FROM " + GenericSoundModelContract.TABLE 105a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra + " WHERE " + GenericSoundModelContract.KEY_MODEL_UUID + "= '" + 106a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra model_uuid + "'"; 107a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra SQLiteDatabase db = getReadableDatabase(); 108a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra Cursor c = db.rawQuery(selectQuery, null); 109a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra try { 110a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (c.moveToFirst()) { 111a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra do { 112a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra byte[] data = c.getBlob(c.getColumnIndex( 113a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra GenericSoundModelContract.KEY_DATA)); 114a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra String vendor_uuid = c.getString( 115a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra c.getColumnIndex(GenericSoundModelContract.KEY_VENDOR_UUID)); 116a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra return new GenericSoundModel(model_uuid, UUID.fromString(vendor_uuid), 117a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra data); 118a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } while (c.moveToNext()); 119a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 120a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } finally { 121a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra c.close(); 122a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra db.close(); 123a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 124a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 125a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra return null; 126a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 127a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 128a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public boolean deleteGenericSoundModel(UUID model_uuid) { 129a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra synchronized(this) { 130a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra GenericSoundModel soundModel = getGenericSoundModel(model_uuid); 131a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (soundModel == null) { 132a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra return false; 133a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 134a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra // Delete all sound models for the given keyphrase and specified user. 135a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra SQLiteDatabase db = getWritableDatabase(); 136a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra String soundModelClause = GenericSoundModelContract.KEY_MODEL_UUID 137a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra + "='" + soundModel.uuid.toString() + "'"; 138a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra try { 139a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra return db.delete(GenericSoundModelContract.TABLE, soundModelClause, null) != 0; 140a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } finally { 141a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra db.close(); 142a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 143a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 144a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 145a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra} 146