1a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra/**
2a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Copyright (C) 2014 The Android Open Source Project
3a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra *
4a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Licensed under the Apache License, Version 2.0 (the "License");
5a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * you may not use this file except in compliance with the License.
6a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * You may obtain a copy of the License at
7a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra *
8a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra *      http://www.apache.org/licenses/LICENSE-2.0
9a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra *
10a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Unless required by applicable law or agreed to in writing, software
11a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * distributed under the License is distributed on an "AS IS" BASIS,
12a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * See the License for the specific language governing permissions and
14a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * limitations under the License.
15a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra */
16a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
17a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishrapackage com.android.server.soundtrigger;
18a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
19a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.content.ContentValues;
20a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.content.Context;
21a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.database.Cursor;
22a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.database.sqlite.SQLiteDatabase;
23a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.database.sqlite.SQLiteOpenHelper;
24a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.hardware.soundtrigger.SoundTrigger;
25a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
26a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.text.TextUtils;
27a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.util.Slog;
28a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
29a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport java.util.Locale;
30a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport java.util.UUID;
31a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
32a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra/**
33a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Helper to manage the database of the sound models that have been registered on the device.
34a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra *
35a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * @hide
36a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra */
37a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishrapublic class SoundTriggerDbHelper extends SQLiteOpenHelper {
38a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    static final String TAG = "SoundTriggerDbHelper";
39a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    static final boolean DBG = false;
40a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
41a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    private static final String NAME = "st_sound_model.db";
42a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    private static final int VERSION = 1;
43a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
44a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    // Sound trigger-based sound models.
45a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    public static interface GenericSoundModelContract {
46a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        public static final String TABLE = "st_sound_model";
47a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        public static final String KEY_MODEL_UUID = "model_uuid";
48a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        public static final String KEY_VENDOR_UUID = "vendor_uuid";
49a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        public static final String KEY_DATA = "data";
50a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    }
51a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
52a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
53a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    // Table Create Statement for the sound trigger table
54a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    private static final String CREATE_TABLE_ST_SOUND_MODEL = "CREATE TABLE "
55a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            + GenericSoundModelContract.TABLE + "("
56a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            + GenericSoundModelContract.KEY_MODEL_UUID + " TEXT PRIMARY KEY,"
573fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra            + GenericSoundModelContract.KEY_VENDOR_UUID + " TEXT,"
58a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            + GenericSoundModelContract.KEY_DATA + " BLOB" + " )";
59a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
60a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
61a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    public SoundTriggerDbHelper(Context context) {
62a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        super(context, NAME, null, VERSION);
63a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    }
64a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
65a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    @Override
66a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    public void onCreate(SQLiteDatabase db) {
67a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        // creating required tables
68a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        db.execSQL(CREATE_TABLE_ST_SOUND_MODEL);
69a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    }
70a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
71a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    @Override
72a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
73a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        // TODO: For now, drop older tables and recreate new ones.
74a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        db.execSQL("DROP TABLE IF EXISTS " + GenericSoundModelContract.TABLE);
75a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        onCreate(db);
76a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    }
77a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
78a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    /**
79a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra     * Updates the given sound trigger model, adds it, if it doesn't already exist.
80a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra     *
81a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra     */
82a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    public boolean updateGenericSoundModel(GenericSoundModel soundModel) {
83a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        synchronized(this) {
84a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            SQLiteDatabase db = getWritableDatabase();
85a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            ContentValues values = new ContentValues();
86a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.uuid.toString());
87a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            values.put(GenericSoundModelContract.KEY_VENDOR_UUID, soundModel.vendorUuid.toString());
88a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            values.put(GenericSoundModelContract.KEY_DATA, soundModel.data);
89a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
90a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            try {
91a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                return db.insertWithOnConflict(GenericSoundModelContract.TABLE, null, values,
92a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                        SQLiteDatabase.CONFLICT_REPLACE) != -1;
93a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            } finally {
94a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                db.close();
95a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            }
96a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
97a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        }
98a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    }
99a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
100a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    public GenericSoundModel getGenericSoundModel(UUID model_uuid) {
101a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        synchronized(this) {
102a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
103a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            // Find the corresponding sound model ID for the keyphrase.
104a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            String selectQuery = "SELECT  * FROM " + GenericSoundModelContract.TABLE
105a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                    + " WHERE " + GenericSoundModelContract.KEY_MODEL_UUID + "= '" +
106a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                    model_uuid + "'";
107a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            SQLiteDatabase db = getReadableDatabase();
108a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            Cursor c = db.rawQuery(selectQuery, null);
109a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            try {
110a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                if (c.moveToFirst()) {
111a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                    do {
112a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                        byte[] data = c.getBlob(c.getColumnIndex(
113a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                                GenericSoundModelContract.KEY_DATA));
114a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                        String vendor_uuid = c.getString(
115a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                                c.getColumnIndex(GenericSoundModelContract.KEY_VENDOR_UUID));
116a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                        return new GenericSoundModel(model_uuid, UUID.fromString(vendor_uuid),
117a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                                data);
118a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                    } while (c.moveToNext());
119a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                }
120a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            } finally {
121a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                c.close();
122a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                db.close();
123a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            }
124a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        }
125a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        return null;
126a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    }
127a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra
128a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    public boolean deleteGenericSoundModel(UUID model_uuid) {
129a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        synchronized(this) {
130a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            GenericSoundModel soundModel = getGenericSoundModel(model_uuid);
131a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            if (soundModel == null) {
132a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                return false;
133a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            }
134a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            // Delete all sound models for the given keyphrase and specified user.
135a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            SQLiteDatabase db = getWritableDatabase();
136a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            String soundModelClause = GenericSoundModelContract.KEY_MODEL_UUID
137a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                    + "='" + soundModel.uuid.toString() + "'";
138a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            try {
139a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                return db.delete(GenericSoundModelContract.TABLE, soundModelClause, null) != 0;
140a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            } finally {
141a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra                db.close();
142a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra            }
143a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra        }
144a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra    }
145a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra}
146