Home | History | Annotate | Download | only in search
      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 
     17 package com.android.settings.search;
     18 
     19 import android.content.Context;
     20 import android.database.Cursor;
     21 import android.database.sqlite.SQLiteDatabase;
     22 import android.database.sqlite.SQLiteOpenHelper;
     23 import android.os.Build;
     24 import android.util.Log;
     25 
     26 public class IndexDatabaseHelper extends SQLiteOpenHelper {
     27 
     28     private static final String TAG = "IndexDatabaseHelper";
     29 
     30     private static final String DATABASE_NAME = "search_index.db";
     31     private static final int DATABASE_VERSION = 117;
     32 
     33     private static final String INDEX = "index";
     34 
     35     public interface Tables {
     36         String TABLE_PREFS_INDEX = "prefs_index";
     37         String TABLE_SITE_MAP = "site_map";
     38         String TABLE_META_INDEX = "meta_index";
     39         String TABLE_SAVED_QUERIES = "saved_queries";
     40     }
     41 
     42     public interface IndexColumns {
     43         String DOCID = "docid";
     44         String LOCALE = "locale";
     45         String DATA_RANK = "data_rank";
     46         String DATA_TITLE = "data_title";
     47         String DATA_TITLE_NORMALIZED = "data_title_normalized";
     48         String DATA_SUMMARY_ON = "data_summary_on";
     49         String DATA_SUMMARY_ON_NORMALIZED = "data_summary_on_normalized";
     50         String DATA_SUMMARY_OFF = "data_summary_off";
     51         String DATA_SUMMARY_OFF_NORMALIZED = "data_summary_off_normalized";
     52         String DATA_ENTRIES = "data_entries";
     53         String DATA_KEYWORDS = "data_keywords";
     54         String CLASS_NAME = "class_name";
     55         String SCREEN_TITLE = "screen_title";
     56         String INTENT_ACTION = "intent_action";
     57         String INTENT_TARGET_PACKAGE = "intent_target_package";
     58         String INTENT_TARGET_CLASS = "intent_target_class";
     59         String ICON = "icon";
     60         String ENABLED = "enabled";
     61         String DATA_KEY_REF = "data_key_reference";
     62         String USER_ID = "user_id";
     63         String PAYLOAD_TYPE = "payload_type";
     64         String PAYLOAD = "payload";
     65     }
     66 
     67     public interface MetaColumns {
     68         String BUILD = "build";
     69     }
     70 
     71     public interface SavedQueriesColumns {
     72         String QUERY = "query";
     73         String TIME_STAMP = "timestamp";
     74     }
     75 
     76     public interface SiteMapColumns {
     77         String DOCID = "docid";
     78         String PARENT_CLASS = "parent_class";
     79         String CHILD_CLASS = "child_class";
     80         String PARENT_TITLE = "parent_title";
     81         String CHILD_TITLE = "child_title";
     82     }
     83 
     84     private static final String CREATE_INDEX_TABLE =
     85             "CREATE VIRTUAL TABLE " + Tables.TABLE_PREFS_INDEX + " USING fts4" +
     86                     "(" +
     87                     IndexColumns.LOCALE +
     88                     ", " +
     89                     IndexColumns.DATA_RANK +
     90                     ", " +
     91                     IndexColumns.DATA_TITLE +
     92                     ", " +
     93                     IndexColumns.DATA_TITLE_NORMALIZED +
     94                     ", " +
     95                     IndexColumns.DATA_SUMMARY_ON +
     96                     ", " +
     97                     IndexColumns.DATA_SUMMARY_ON_NORMALIZED +
     98                     ", " +
     99                     IndexColumns.DATA_SUMMARY_OFF +
    100                     ", " +
    101                     IndexColumns.DATA_SUMMARY_OFF_NORMALIZED +
    102                     ", " +
    103                     IndexColumns.DATA_ENTRIES +
    104                     ", " +
    105                     IndexColumns.DATA_KEYWORDS +
    106                     ", " +
    107                     IndexColumns.SCREEN_TITLE +
    108                     ", " +
    109                     IndexColumns.CLASS_NAME +
    110                     ", " +
    111                     IndexColumns.ICON +
    112                     ", " +
    113                     IndexColumns.INTENT_ACTION +
    114                     ", " +
    115                     IndexColumns.INTENT_TARGET_PACKAGE +
    116                     ", " +
    117                     IndexColumns.INTENT_TARGET_CLASS +
    118                     ", " +
    119                     IndexColumns.ENABLED +
    120                     ", " +
    121                     IndexColumns.DATA_KEY_REF +
    122                     ", " +
    123                     IndexColumns.USER_ID +
    124                     ", " +
    125                     IndexColumns.PAYLOAD_TYPE +
    126                     ", " +
    127                     IndexColumns.PAYLOAD +
    128                     ");";
    129 
    130     private static final String CREATE_META_TABLE =
    131             "CREATE TABLE " + Tables.TABLE_META_INDEX +
    132                     "(" +
    133                     MetaColumns.BUILD + " VARCHAR(32) NOT NULL" +
    134                     ")";
    135 
    136     private static final String CREATE_SAVED_QUERIES_TABLE =
    137             "CREATE TABLE " + Tables.TABLE_SAVED_QUERIES +
    138                     "(" +
    139                     SavedQueriesColumns.QUERY + " VARCHAR(64) NOT NULL" +
    140                     ", " +
    141                     SavedQueriesColumns.TIME_STAMP + " INTEGER" +
    142                     ")";
    143 
    144     private static final String CREATE_SITE_MAP_TABLE =
    145             "CREATE VIRTUAL TABLE " + Tables.TABLE_SITE_MAP + " USING fts4" +
    146                     "(" +
    147                     SiteMapColumns.PARENT_CLASS +
    148                     ", " +
    149                     SiteMapColumns.CHILD_CLASS +
    150                     ", " +
    151                     SiteMapColumns.PARENT_TITLE +
    152                     ", " +
    153                     SiteMapColumns.CHILD_TITLE +
    154                     ")";
    155     private static final String INSERT_BUILD_VERSION =
    156             "INSERT INTO " + Tables.TABLE_META_INDEX +
    157                     " VALUES ('" + Build.VERSION.INCREMENTAL + "');";
    158 
    159     private static final String SELECT_BUILD_VERSION =
    160             "SELECT " + MetaColumns.BUILD + " FROM " + Tables.TABLE_META_INDEX + " LIMIT 1;";
    161 
    162     private static IndexDatabaseHelper sSingleton;
    163 
    164     private final Context mContext;
    165 
    166     public static synchronized IndexDatabaseHelper getInstance(Context context) {
    167         if (sSingleton == null) {
    168             sSingleton = new IndexDatabaseHelper(context);
    169         }
    170         return sSingleton;
    171     }
    172 
    173     public IndexDatabaseHelper(Context context) {
    174         super(context, DATABASE_NAME, null, DATABASE_VERSION);
    175         mContext = context;
    176     }
    177 
    178     @Override
    179     public void onCreate(SQLiteDatabase db) {
    180         bootstrapDB(db);
    181     }
    182 
    183     private void bootstrapDB(SQLiteDatabase db) {
    184         db.execSQL(CREATE_INDEX_TABLE);
    185         db.execSQL(CREATE_META_TABLE);
    186         db.execSQL(CREATE_SAVED_QUERIES_TABLE);
    187         db.execSQL(CREATE_SITE_MAP_TABLE);
    188         db.execSQL(INSERT_BUILD_VERSION);
    189         Log.i(TAG, "Bootstrapped database");
    190     }
    191 
    192     @Override
    193     public void onOpen(SQLiteDatabase db) {
    194         super.onOpen(db);
    195 
    196         Log.i(TAG, "Using schema version: " + db.getVersion());
    197 
    198         if (!Build.VERSION.INCREMENTAL.equals(getBuildVersion(db))) {
    199             Log.w(TAG, "Index needs to be rebuilt as build-version is not the same");
    200             // We need to drop the tables and recreate them
    201             reconstruct(db);
    202         } else {
    203             Log.i(TAG, "Index is fine");
    204         }
    205     }
    206 
    207     @Override
    208     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    209         if (oldVersion < DATABASE_VERSION) {
    210             Log.w(TAG, "Detected schema version '" + oldVersion + "'. " +
    211                     "Index needs to be rebuilt for schema version '" + newVersion + "'.");
    212             // We need to drop the tables and recreate them
    213             reconstruct(db);
    214         }
    215     }
    216 
    217     @Override
    218     public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    219         Log.w(TAG, "Detected schema version '" + oldVersion + "'. " +
    220                 "Index needs to be rebuilt for schema version '" + newVersion + "'.");
    221         // We need to drop the tables and recreate them
    222         reconstruct(db);
    223     }
    224 
    225     public void reconstruct(SQLiteDatabase db) {
    226         dropTables(db);
    227         bootstrapDB(db);
    228     }
    229 
    230     private String getBuildVersion(SQLiteDatabase db) {
    231         String version = null;
    232         Cursor cursor = null;
    233         try {
    234             cursor = db.rawQuery(SELECT_BUILD_VERSION, null);
    235             if (cursor.moveToFirst()) {
    236                 version = cursor.getString(0);
    237             }
    238         } catch (Exception e) {
    239             Log.e(TAG, "Cannot get build version from Index metadata");
    240         } finally {
    241             if (cursor != null) {
    242                 cursor.close();
    243             }
    244         }
    245         return version;
    246     }
    247 
    248     public static void clearCachedIndexed(Context context) {
    249         context.getSharedPreferences(INDEX, 0).edit().clear().commit();
    250     }
    251 
    252     public static void setLocaleIndexed(Context context, String locale) {
    253         context.getSharedPreferences(INDEX, 0).edit().putBoolean(locale, true).commit();
    254     }
    255 
    256     public static boolean isLocaleAlreadyIndexed(Context context, String locale) {
    257         return context.getSharedPreferences(INDEX, 0).getBoolean(locale, false);
    258     }
    259 
    260     public static boolean isBuildIndexed(Context context, String buildNo) {
    261         return context.getSharedPreferences(INDEX, 0).getBoolean(buildNo, false);
    262     }
    263 
    264     public static void setBuildIndexed(Context context, String buildNo) {
    265         context.getSharedPreferences(INDEX, 0).edit().putBoolean(buildNo, true).commit();
    266     }
    267 
    268     private void dropTables(SQLiteDatabase db) {
    269         clearCachedIndexed(mContext);
    270         db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_META_INDEX);
    271         db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_PREFS_INDEX);
    272         db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_SAVED_QUERIES);
    273         db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_SITE_MAP);
    274     }
    275 }
    276