DatabaseHelper.java revision 8ecaf5f5cfd18e0436db1a27ccf46a063e9aacd7
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.SQLiteDatabase.CursorFactory;
24import android.database.sqlite.SQLiteOpenHelper;
25import android.hardware.soundtrigger.SoundTrigger;
26import android.hardware.soundtrigger.Keyphrase;
27import android.hardware.soundtrigger.KeyphraseSoundModel;
28import android.util.Slog;
29
30import java.util.ArrayList;
31import java.util.List;
32import java.util.UUID;
33
34/**
35 * Helper to manage the database of the sound models that have been registered on the device.
36 *
37 * @hide
38 */
39public class DatabaseHelper extends SQLiteOpenHelper {
40    static final String TAG = "SoundModelDBHelper";
41
42    private static final String NAME = "sound_model.db";
43    private static final int VERSION = 1;
44
45    public static interface KeyphraseContract {
46        public static final String TABLE = "keyphrase";
47        public static final String KEY_ID = "_id";
48        public static final String KEY_RECOGNITION_MODES = "modes";
49        public static final String KEY_LOCALE = "locale";
50        public static final String KEY_HINT_TEXT = "hint_text";
51        public static final String KEY_USERS = "users";
52        public static final String KEY_SOUND_MODEL_ID = "sound_model_id";
53    }
54
55    public static interface SoundModelContract {
56        public static final String TABLE = "sound_model";
57        public static final String KEY_ID = "_id";
58        public static final String KEY_TYPE = "type";
59        public static final String KEY_DATA = "data";
60    }
61
62    // Table Create Statements
63    private static final String CREATE_TABLE_KEYPRHASES = "CREATE TABLE "
64            + KeyphraseContract.TABLE + "("
65            + KeyphraseContract.KEY_ID + " INTEGER PRIMARY KEY,"
66            + KeyphraseContract.KEY_RECOGNITION_MODES + " INTEGER,"
67            + KeyphraseContract.KEY_USERS + " INTEGER,"
68            + KeyphraseContract.KEY_SOUND_MODEL_ID + " TEXT,"
69            + KeyphraseContract.KEY_LOCALE + " TEXT,"
70            + KeyphraseContract.KEY_HINT_TEXT + " TEXT" + ")";
71
72    private static final String CREATE_TABLE_SOUND_MODEL = "CREATE TABLE "
73            + SoundModelContract.TABLE + "("
74            + SoundModelContract.KEY_ID + " TEXT PRIMARY KEY,"
75            + SoundModelContract.KEY_TYPE + " INTEGER,"
76            + SoundModelContract.KEY_DATA + " BLOB" + ")";
77
78    public DatabaseHelper(Context context, CursorFactory factory) {
79        super(context, NAME, null, VERSION);
80    }
81
82    @Override
83    public void onCreate(SQLiteDatabase db) {
84        // creating required tables
85        db.execSQL(CREATE_TABLE_KEYPRHASES);
86        db.execSQL(CREATE_TABLE_SOUND_MODEL);
87    }
88
89    @Override
90    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
91        // TODO: For now, drop older tables and recreate new ones.
92        db.execSQL("DROP TABLE IF EXISTS " + KeyphraseContract.TABLE);
93        db.execSQL("DROP TABLE IF EXISTS " + SoundModelContract.TABLE);
94        onCreate(db);
95    }
96
97    /**
98     * TODO: Change to addOrUpdate to handle changes here.
99     */
100    public void addKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
101        SQLiteDatabase db = this.getWritableDatabase();
102        ContentValues values = new ContentValues();
103        // Generate a random ID for the model.
104        values.put(SoundModelContract.KEY_ID, soundModel.uuid.toString());
105        values.put(SoundModelContract.KEY_DATA, soundModel.data);
106        values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE);
107
108        if (db.insert(SoundModelContract.TABLE, null, values) != -1) {
109            for (Keyphrase keyphrase : soundModel.keyphrases) {
110                addKeyphrase(soundModel.uuid, keyphrase);
111            }
112        } else {
113            Slog.w(TAG, "Failed to persist sound model to database");
114        }
115    }
116
117    /**
118     * TODO(sansid): Change to addOrUpdate to handle changes here.
119     */
120    private void addKeyphrase(UUID modelId, Keyphrase keyphrase) {
121        SQLiteDatabase db = this.getWritableDatabase();
122        ContentValues values = new ContentValues();
123        values.put(KeyphraseContract.KEY_ID, keyphrase.id);
124        values.put(KeyphraseContract.KEY_RECOGNITION_MODES, keyphrase.recognitionModeFlags);
125        values.put(KeyphraseContract.KEY_SOUND_MODEL_ID, keyphrase.id);
126        values.put(KeyphraseContract.KEY_HINT_TEXT, keyphrase.hintText);
127        values.put(KeyphraseContract.KEY_LOCALE, keyphrase.locale);
128        if (db.insert(KeyphraseContract.TABLE, null, values) == -1) {
129            Slog.w(TAG, "Failed to persist keyphrase to database");
130        }
131    }
132
133    /**
134     * Lists all the keyphrase sound models currently registered with the system.
135     */
136    public List<KeyphraseSoundModel> getKephraseSoundModels() {
137        List<KeyphraseSoundModel> models = new ArrayList<>();
138        String selectQuery = "SELECT  * FROM " + SoundModelContract.TABLE;
139        SQLiteDatabase db = this.getReadableDatabase();
140        Cursor c = db.rawQuery(selectQuery, null);
141
142        // looping through all rows and adding to list
143        if (c.moveToFirst()) {
144            do {
145                int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
146                if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) {
147                    // Ignore non-keyphrase sound models.
148                    continue;
149                }
150                String id = c.getString(c.getColumnIndex(SoundModelContract.KEY_ID));
151                byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
152                // Get all the keyphrases for this this sound model.
153                models.add(new KeyphraseSoundModel(
154                        UUID.fromString(id), data, getKeyphrasesForSoundModel(id)));
155            } while (c.moveToNext());
156        }
157        return models;
158    }
159
160    private Keyphrase[] getKeyphrasesForSoundModel(String modelId) {
161        List<Keyphrase> keyphrases = new ArrayList<>();
162        String selectQuery = "SELECT  * FROM " + KeyphraseContract.TABLE
163                + " WHERE " + KeyphraseContract.KEY_SOUND_MODEL_ID + " = '" + modelId + "'";
164        SQLiteDatabase db = this.getReadableDatabase();
165        Cursor c = db.rawQuery(selectQuery, null);
166
167        // looping through all rows and adding to list
168        if (c.moveToFirst()) {
169            do {
170                int id = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_ID));
171                int modes = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_RECOGNITION_MODES));
172                int[] users = {c.getInt(c.getColumnIndex(KeyphraseContract.KEY_USERS))};
173                String locale = c.getString(c.getColumnIndex(KeyphraseContract.KEY_LOCALE));
174                String hintText = c.getString(c.getColumnIndex(KeyphraseContract.KEY_HINT_TEXT));
175
176                keyphrases.add(new Keyphrase(id, hintText, locale, modes, users));
177            } while (c.moveToNext());
178        }
179        Keyphrase[] keyphraseArr = new Keyphrase[keyphrases.size()];
180        keyphrases.toArray(keyphraseArr);
181        return keyphraseArr;
182    }
183}
184