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