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