DatabaseHelper.java revision 2883ba69751de69811a38f086ecbe4c2032ca87d
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 = this.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 &= addKeyphrase(soundModel.uuid, keyphrase);
109            }
110            return status;
111        } else {
112            Slog.w(TAG, "Failed to persist sound model to database");
113            return false;
114        }
115    }
116
117    /**
118     * TODO(sansid): Change to addOrUpdate to handle changes here.
119     */
120    private boolean 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            return true;
130        } else {
131            Slog.w(TAG, "Failed to persist keyphrase to database");
132            return false;
133        }
134    }
135
136    /**
137     * Lists all the keyphrase sound models currently registered with the system.
138     */
139    public List<KeyphraseSoundModel> getKephraseSoundModels() {
140        List<KeyphraseSoundModel> models = new ArrayList<>();
141        String selectQuery = "SELECT  * FROM " + SoundModelContract.TABLE;
142        SQLiteDatabase db = this.getReadableDatabase();
143        Cursor c = db.rawQuery(selectQuery, null);
144
145        // looping through all rows and adding to list
146        if (c.moveToFirst()) {
147            do {
148                int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
149                if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) {
150                    // Ignore non-keyphrase sound models.
151                    continue;
152                }
153                String id = c.getString(c.getColumnIndex(SoundModelContract.KEY_ID));
154                byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
155                // Get all the keyphrases for this this sound model.
156                models.add(new KeyphraseSoundModel(
157                        UUID.fromString(id), data, getKeyphrasesForSoundModel(id)));
158            } while (c.moveToNext());
159        }
160        return models;
161    }
162
163    private Keyphrase[] getKeyphrasesForSoundModel(String modelId) {
164        List<Keyphrase> keyphrases = new ArrayList<>();
165        String selectQuery = "SELECT  * FROM " + KeyphraseContract.TABLE
166                + " WHERE " + KeyphraseContract.KEY_SOUND_MODEL_ID + " = '" + modelId + "'";
167        SQLiteDatabase db = this.getReadableDatabase();
168        Cursor c = db.rawQuery(selectQuery, null);
169
170        // looping through all rows and adding to list
171        if (c.moveToFirst()) {
172            do {
173                int id = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_ID));
174                int modes = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_RECOGNITION_MODES));
175                int[] users = {c.getInt(c.getColumnIndex(KeyphraseContract.KEY_USERS))};
176                String locale = c.getString(c.getColumnIndex(KeyphraseContract.KEY_LOCALE));
177                String hintText = c.getString(c.getColumnIndex(KeyphraseContract.KEY_HINT_TEXT));
178
179                keyphrases.add(new Keyphrase(id, hintText, locale, modes, users));
180            } while (c.moveToNext());
181        }
182        Keyphrase[] keyphraseArr = new Keyphrase[keyphrases.size()];
183        keyphrases.toArray(keyphraseArr);
184        return keyphraseArr;
185    }
186}
187