DatabaseHelper.java revision 7444c906faef1f7a9a6e6f7a443ba156f1e856be
1/** 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.voiceinteraction; 18 19import android.content.ContentValues; 20import android.content.Context; 21import android.database.Cursor; 22import android.database.sqlite.SQLiteDatabase; 23import android.database.sqlite.SQLiteOpenHelper; 24import android.hardware.soundtrigger.SoundTrigger; 25import android.hardware.soundtrigger.Keyphrase; 26import android.hardware.soundtrigger.KeyphraseSoundModel; 27import android.util.Slog; 28 29import java.util.ArrayList; 30import java.util.List; 31import java.util.UUID; 32 33/** 34 * Helper to manage the database of the sound models that have been registered on the device. 35 * 36 * @hide 37 */ 38public class DatabaseHelper extends SQLiteOpenHelper { 39 static final String TAG = "SoundModelDBHelper"; 40 41 private static final String NAME = "sound_model.db"; 42 private static final int VERSION = 1; 43 44 public static interface KeyphraseContract { 45 public static final String TABLE = "keyphrase"; 46 public static final String KEY_ID = "_id"; 47 public static final String KEY_RECOGNITION_MODES = "modes"; 48 public static final String KEY_LOCALE = "locale"; 49 public static final String KEY_HINT_TEXT = "hint_text"; 50 public static final String KEY_USERS = "users"; 51 public static final String KEY_SOUND_MODEL_ID = "sound_model_id"; 52 } 53 54 public static interface SoundModelContract { 55 public static final String TABLE = "sound_model"; 56 public static final String KEY_ID = "_id"; 57 public static final String KEY_TYPE = "type"; 58 public static final String KEY_DATA = "data"; 59 } 60 61 // Table Create Statements 62 private static final String CREATE_TABLE_KEYPRHASES = "CREATE TABLE " 63 + KeyphraseContract.TABLE + "(" 64 + KeyphraseContract.KEY_ID + " INTEGER PRIMARY KEY," 65 + KeyphraseContract.KEY_RECOGNITION_MODES + " INTEGER," 66 + KeyphraseContract.KEY_USERS + " INTEGER," 67 + KeyphraseContract.KEY_SOUND_MODEL_ID + " TEXT," 68 + KeyphraseContract.KEY_LOCALE + " TEXT," 69 + KeyphraseContract.KEY_HINT_TEXT + " TEXT" + ")"; 70 71 private static final String CREATE_TABLE_SOUND_MODEL = "CREATE TABLE " 72 + SoundModelContract.TABLE + "(" 73 + SoundModelContract.KEY_ID + " TEXT PRIMARY KEY," 74 + SoundModelContract.KEY_TYPE + " INTEGER," 75 + SoundModelContract.KEY_DATA + " BLOB" + ")"; 76 77 public DatabaseHelper(Context context) { 78 super(context, NAME, null, VERSION); 79 } 80 81 @Override 82 public void onCreate(SQLiteDatabase db) { 83 // creating required tables 84 db.execSQL(CREATE_TABLE_KEYPRHASES); 85 db.execSQL(CREATE_TABLE_SOUND_MODEL); 86 } 87 88 @Override 89 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 90 // TODO: For now, drop older tables and recreate new ones. 91 db.execSQL("DROP TABLE IF EXISTS " + KeyphraseContract.TABLE); 92 db.execSQL("DROP TABLE IF EXISTS " + SoundModelContract.TABLE); 93 onCreate(db); 94 } 95 96 public boolean addOrUpdateKeyphraseSoundModel(KeyphraseSoundModel soundModel) { 97 SQLiteDatabase db = getWritableDatabase(); 98 ContentValues values = new ContentValues(); 99 // Generate a random ID for the model. 100 values.put(SoundModelContract.KEY_ID, soundModel.uuid.toString()); 101 values.put(SoundModelContract.KEY_DATA, soundModel.data); 102 values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE); 103 104 boolean status = true; 105 if (db.insertWithOnConflict( 106 SoundModelContract.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE) != -1) { 107 for (Keyphrase keyphrase : soundModel.keyphrases) { 108 status &= addOrUpdateKeyphrase(db, soundModel.uuid, keyphrase); 109 } 110 db.close(); 111 return status; 112 } else { 113 Slog.w(TAG, "Failed to persist sound model to database"); 114 db.close(); 115 return false; 116 } 117 } 118 119 private boolean addOrUpdateKeyphrase(SQLiteDatabase db, UUID modelId, Keyphrase keyphrase) { 120 ContentValues values = new ContentValues(); 121 values.put(KeyphraseContract.KEY_ID, keyphrase.id); 122 values.put(KeyphraseContract.KEY_RECOGNITION_MODES, keyphrase.recognitionModeFlags); 123 values.put(KeyphraseContract.KEY_SOUND_MODEL_ID, modelId.toString()); 124 values.put(KeyphraseContract.KEY_HINT_TEXT, keyphrase.hintText); 125 values.put(KeyphraseContract.KEY_LOCALE, keyphrase.locale); 126 if (db.insertWithOnConflict( 127 KeyphraseContract.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE) != -1) { 128 return true; 129 } else { 130 Slog.w(TAG, "Failed to persist keyphrase to database"); 131 return false; 132 } 133 } 134 135 /** 136 * Deletes the sound model and associated keyphrases. 137 */ 138 public boolean deleteKeyphraseSoundModel(UUID uuid) { 139 SQLiteDatabase db = getWritableDatabase(); 140 String modelId = uuid.toString(); 141 String soundModelClause = SoundModelContract.KEY_ID + "=" + modelId; 142 boolean status = true; 143 if (db.delete(SoundModelContract.TABLE, soundModelClause, null) == 0) { 144 Slog.w(TAG, "No sound models deleted from the database"); 145 status = false; 146 } 147 String keyphraseClause = KeyphraseContract.KEY_SOUND_MODEL_ID + "=" + modelId; 148 if (db.delete(KeyphraseContract.TABLE, keyphraseClause, null) == 0) { 149 Slog.w(TAG, "No keyphrases deleted from the database"); 150 status = false; 151 } 152 db.close(); 153 return status; 154 } 155 156 /** 157 * Lists all the keyphrase sound models currently registered with the system. 158 */ 159 public List<KeyphraseSoundModel> getKephraseSoundModels() { 160 List<KeyphraseSoundModel> models = new ArrayList<>(); 161 String selectQuery = "SELECT * FROM " + SoundModelContract.TABLE; 162 SQLiteDatabase db = getReadableDatabase(); 163 Cursor c = db.rawQuery(selectQuery, null); 164 165 // looping through all rows and adding to list 166 if (c.moveToFirst()) { 167 do { 168 int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE)); 169 if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) { 170 // Ignore non-keyphrase sound models. 171 continue; 172 } 173 String id = c.getString(c.getColumnIndex(SoundModelContract.KEY_ID)); 174 byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA)); 175 // Get all the keyphrases for this this sound model. 176 models.add(new KeyphraseSoundModel( 177 UUID.fromString(id), data, getKeyphrasesForSoundModel(db, id))); 178 } while (c.moveToNext()); 179 } 180 c.close(); 181 db.close(); 182 return models; 183 } 184 185 private Keyphrase[] getKeyphrasesForSoundModel(SQLiteDatabase db, String modelId) { 186 List<Keyphrase> keyphrases = new ArrayList<>(); 187 String selectQuery = "SELECT * FROM " + KeyphraseContract.TABLE 188 + " WHERE " + KeyphraseContract.KEY_SOUND_MODEL_ID + " = '" + modelId + "'"; 189 Cursor c = db.rawQuery(selectQuery, null); 190 191 // looping through all rows and adding to list 192 if (c.moveToFirst()) { 193 do { 194 int id = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_ID)); 195 int modes = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_RECOGNITION_MODES)); 196 int[] users = {c.getInt(c.getColumnIndex(KeyphraseContract.KEY_USERS))}; 197 String locale = c.getString(c.getColumnIndex(KeyphraseContract.KEY_LOCALE)); 198 String hintText = c.getString(c.getColumnIndex(KeyphraseContract.KEY_HINT_TEXT)); 199 200 keyphrases.add(new Keyphrase(id, hintText, locale, modes, users)); 201 } while (c.moveToNext()); 202 } 203 Keyphrase[] keyphraseArr = new Keyphrase[keyphrases.size()]; 204 keyphrases.toArray(keyphraseArr); 205 c.close(); 206 return keyphraseArr; 207 } 208} 209