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 17 package com.android.server.soundtrigger; 18 19 import android.content.ContentValues; 20 import android.content.Context; 21 import android.database.Cursor; 22 import android.database.sqlite.SQLiteDatabase; 23 import android.database.sqlite.SQLiteOpenHelper; 24 import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel; 25 import android.util.Slog; 26 27 import java.io.PrintWriter; 28 import java.util.UUID; 29 30 /** 31 * Helper to manage the database of the sound models that have been registered on the device. 32 * 33 * @hide 34 */ 35 public class SoundTriggerDbHelper extends SQLiteOpenHelper { 36 static final String TAG = "SoundTriggerDbHelper"; 37 static final boolean DBG = false; 38 39 private static final String NAME = "st_sound_model.db"; 40 private static final int VERSION = 2; 41 42 // Sound trigger-based sound models. 43 public static interface GenericSoundModelContract { 44 public static final String TABLE = "st_sound_model"; 45 public static final String KEY_MODEL_UUID = "model_uuid"; 46 public static final String KEY_VENDOR_UUID = "vendor_uuid"; 47 public static final String KEY_DATA = "data"; 48 public static final String KEY_MODEL_VERSION = "model_version"; 49 } 50 51 // Table Create Statement for the sound trigger table 52 private static final String CREATE_TABLE_ST_SOUND_MODEL = "CREATE TABLE " 53 + GenericSoundModelContract.TABLE + "(" 54 + GenericSoundModelContract.KEY_MODEL_UUID + " TEXT PRIMARY KEY," 55 + GenericSoundModelContract.KEY_VENDOR_UUID + " TEXT," 56 + GenericSoundModelContract.KEY_DATA + " BLOB," 57 + GenericSoundModelContract.KEY_MODEL_VERSION + " INTEGER" + " )"; 58 59 SoundTriggerDbHelper(Context context)60 public SoundTriggerDbHelper(Context context) { 61 super(context, NAME, null, VERSION); 62 } 63 64 @Override onCreate(SQLiteDatabase db)65 public void onCreate(SQLiteDatabase db) { 66 // creating required tables 67 db.execSQL(CREATE_TABLE_ST_SOUND_MODEL); 68 } 69 70 @Override onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)71 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 72 if (oldVersion == 1) { 73 // In version 2, a model version number was added. 74 Slog.d(TAG, "Adding model version column"); 75 db.execSQL("ALTER TABLE " + GenericSoundModelContract.TABLE + " ADD COLUMN " 76 + GenericSoundModelContract.KEY_MODEL_VERSION + " INTEGER DEFAULT -1"); 77 oldVersion++; 78 } 79 } 80 81 /** 82 * Updates the given sound trigger model, adds it, if it doesn't already exist. 83 * 84 */ updateGenericSoundModel(GenericSoundModel soundModel)85 public boolean updateGenericSoundModel(GenericSoundModel soundModel) { 86 synchronized(this) { 87 SQLiteDatabase db = getWritableDatabase(); 88 ContentValues values = new ContentValues(); 89 values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.getUuid().toString()); 90 values.put(GenericSoundModelContract.KEY_VENDOR_UUID, 91 soundModel.getVendorUuid().toString()); 92 values.put(GenericSoundModelContract.KEY_DATA, soundModel.getData()); 93 values.put(GenericSoundModelContract.KEY_MODEL_VERSION, soundModel.getVersion()); 94 95 try { 96 return db.insertWithOnConflict(GenericSoundModelContract.TABLE, null, values, 97 SQLiteDatabase.CONFLICT_REPLACE) != -1; 98 } finally { 99 db.close(); 100 } 101 102 } 103 } 104 getGenericSoundModel(UUID model_uuid)105 public GenericSoundModel getGenericSoundModel(UUID model_uuid) { 106 synchronized(this) { 107 108 // Find the corresponding sound model ID for the keyphrase. 109 String selectQuery = "SELECT * FROM " + GenericSoundModelContract.TABLE 110 + " WHERE " + GenericSoundModelContract.KEY_MODEL_UUID + "= '" + 111 model_uuid + "'"; 112 SQLiteDatabase db = getReadableDatabase(); 113 Cursor c = db.rawQuery(selectQuery, null); 114 try { 115 if (c.moveToFirst()) { 116 do { 117 byte[] data = c.getBlob(c.getColumnIndex( 118 GenericSoundModelContract.KEY_DATA)); 119 String vendor_uuid = c.getString( 120 c.getColumnIndex(GenericSoundModelContract.KEY_VENDOR_UUID)); 121 int version = c.getInt( 122 c.getColumnIndex(GenericSoundModelContract.KEY_MODEL_VERSION)); 123 return new GenericSoundModel(model_uuid, UUID.fromString(vendor_uuid), 124 data, version); 125 } while (c.moveToNext()); 126 } 127 } finally { 128 c.close(); 129 db.close(); 130 } 131 } 132 return null; 133 } 134 deleteGenericSoundModel(UUID model_uuid)135 public boolean deleteGenericSoundModel(UUID model_uuid) { 136 synchronized(this) { 137 GenericSoundModel soundModel = getGenericSoundModel(model_uuid); 138 if (soundModel == null) { 139 return false; 140 } 141 // Delete all sound models for the given keyphrase and specified user. 142 SQLiteDatabase db = getWritableDatabase(); 143 String soundModelClause = GenericSoundModelContract.KEY_MODEL_UUID 144 + "='" + soundModel.getUuid().toString() + "'"; 145 try { 146 return db.delete(GenericSoundModelContract.TABLE, soundModelClause, null) != 0; 147 } finally { 148 db.close(); 149 } 150 } 151 } 152 dump(PrintWriter pw)153 public void dump(PrintWriter pw) { 154 synchronized(this) { 155 String selectQuery = "SELECT * FROM " + GenericSoundModelContract.TABLE; 156 SQLiteDatabase db = getReadableDatabase(); 157 Cursor c = db.rawQuery(selectQuery, null); 158 try { 159 pw.println(" Enrolled GenericSoundModels:"); 160 if (c.moveToFirst()) { 161 String[] columnNames = c.getColumnNames(); 162 do { 163 for (String name : columnNames) { 164 int colNameIndex = c.getColumnIndex(name); 165 int type = c.getType(colNameIndex); 166 switch (type) { 167 case Cursor.FIELD_TYPE_STRING: 168 pw.printf(" %s: %s\n", name, 169 c.getString(colNameIndex)); 170 break; 171 case Cursor.FIELD_TYPE_BLOB: 172 pw.printf(" %s: data blob\n", name); 173 break; 174 case Cursor.FIELD_TYPE_INTEGER: 175 pw.printf(" %s: %d\n", name, 176 c.getInt(colNameIndex)); 177 break; 178 case Cursor.FIELD_TYPE_FLOAT: 179 pw.printf(" %s: %f\n", name, 180 c.getFloat(colNameIndex)); 181 break; 182 case Cursor.FIELD_TYPE_NULL: 183 pw.printf(" %s: null\n", name); 184 break; 185 } 186 } 187 pw.println(); 188 } while (c.moveToNext()); 189 } 190 } finally { 191 c.close(); 192 db.close(); 193 } 194 } 195 } 196 } 197