1a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang/* 2a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * Copyright (C) 2017 The Android Open Source Project 3a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * 4a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 5a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * you may not use this file except in compliance with the License. 6a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * You may obtain a copy of the License at 7a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * 8a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * http://www.apache.org/licenses/LICENSE-2.0 9a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * 10a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * Unless required by applicable law or agreed to in writing, software 11a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * distributed under the License is distributed on an "AS IS" BASIS, 12a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * See the License for the specific language governing permissions and 14a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * limitations under the License. 152078bc2358031ef3a191900d9036daf4251911c1Matthew Fritze * 16a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang */ 17a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 182078bc2358031ef3a191900d9036daf4251911c1Matthew Fritzepackage com.android.settings.search; 19a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 20a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangimport android.content.ContentValues; 21a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangimport android.content.Context; 22a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangimport android.database.sqlite.SQLiteDatabase; 23a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangimport android.database.sqlite.SQLiteException; 24a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangimport android.util.Log; 25a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 26a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangimport com.android.settings.search.IndexDatabaseHelper; 27a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangimport com.android.settings.utils.AsyncLoader; 28a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 29a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangimport static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES; 30a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 31a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang/** 32a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang * A background task to update saved queries. 33a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang */ 34a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhangpublic class SavedQueryRecorder extends AsyncLoader<Void> { 35a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 36a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang private static final String LOG_TAG = "SavedQueryRecorder"; 37a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 38a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang // Max number of saved search queries (who will be used for proposing suggestions) 39a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang private static long MAX_SAVED_SEARCH_QUERY = 64; 40a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 41a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang private final String mQuery; 42a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 43a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang public SavedQueryRecorder(Context context, String query) { 44a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang super(context); 45a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang mQuery = query; 46a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } 47a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 48a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang @Override 49a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang protected void onDiscardResult(Void result) { 50a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 51a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } 52a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 53a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang @Override 54a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang public Void loadInBackground() { 55a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang final long now = System.currentTimeMillis(); 56a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 57a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang final ContentValues values = new ContentValues(); 58a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang values.put(IndexDatabaseHelper.SavedQueriesColumns.QUERY, mQuery); 59a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang values.put(IndexDatabaseHelper.SavedQueriesColumns.TIME_STAMP, now); 60a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 61a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang final SQLiteDatabase database = getWritableDatabase(); 62a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang if (database == null) { 63a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang return null; 64a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } 65a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 66a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang long lastInsertedRowId; 67a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang try { 68a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang // First, delete all saved queries that are the same 69a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang database.delete(TABLE_SAVED_QUERIES, 70a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang IndexDatabaseHelper.SavedQueriesColumns.QUERY + " = ?", 71a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang new String[]{mQuery}); 72a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 73a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang // Second, insert the saved query 74a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang lastInsertedRowId = database.insertOrThrow(TABLE_SAVED_QUERIES, null, values); 75a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 76a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang // Last, remove "old" saved queries 77a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang final long delta = lastInsertedRowId - MAX_SAVED_SEARCH_QUERY; 78a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang if (delta > 0) { 79a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang int count = database.delete(TABLE_SAVED_QUERIES, 80a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang "rowId <= ?", 81a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang new String[]{Long.toString(delta)}); 82a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang Log.d(LOG_TAG, "Deleted '" + count + "' saved Search query(ies)"); 83a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } 84a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } catch (Exception e) { 85a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang Log.d(LOG_TAG, "Cannot update saved Search queries", e); 86a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } 87a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang return null; 88a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } 89a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang 90a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang private SQLiteDatabase getWritableDatabase() { 91a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang try { 92a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang return IndexDatabaseHelper.getInstance(getContext()).getWritableDatabase(); 93a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } catch (SQLiteException e) { 94a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang Log.e(LOG_TAG, "Cannot open writable database", e); 95a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang return null; 96a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } 97a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang } 98a8b089db8a6d495a18dc3ad91d3bd84b042fb004Fan Zhang} 99