Home | History | Annotate | Download | only in util
      1 package com.android.launcher3.util;
      2 
      3 import android.content.ContentValues;
      4 import android.content.Context;
      5 import android.database.Cursor;
      6 import android.database.sqlite.SQLiteDatabase;
      7 import android.database.sqlite.SQLiteException;
      8 import android.database.sqlite.SQLiteFullException;
      9 import android.database.sqlite.SQLiteOpenHelper;
     10 import android.util.Log;
     11 
     12 import com.android.launcher3.Utilities;
     13 import com.android.launcher3.config.FeatureFlags;
     14 
     15 /**
     16  * An extension of {@link SQLiteOpenHelper} with utility methods for a single table cache DB.
     17  * Any exception during write operations are ignored, and any version change causes a DB reset.
     18  */
     19 public abstract class SQLiteCacheHelper {
     20     private static final String TAG = "SQLiteCacheHelper";
     21 
     22     private static final boolean NO_ICON_CACHE = FeatureFlags.IS_DOGFOOD_BUILD &&
     23             Utilities.isPropertyEnabled(LogConfig.MEMORY_ONLY_ICON_CACHE);
     24 
     25     private final String mTableName;
     26     private final MySQLiteOpenHelper mOpenHelper;
     27 
     28     private boolean mIgnoreWrites;
     29 
     30     public SQLiteCacheHelper(Context context, String name, int version, String tableName) {
     31         if (NO_ICON_CACHE) {
     32             name = null;
     33         }
     34         mTableName = tableName;
     35         mOpenHelper = new MySQLiteOpenHelper(context, name, version);
     36 
     37         mIgnoreWrites = false;
     38     }
     39 
     40     /**
     41      * @see SQLiteDatabase#delete(String, String, String[])
     42      */
     43     public void delete(String whereClause, String[] whereArgs) {
     44         if (mIgnoreWrites) {
     45             return;
     46         }
     47         try {
     48             mOpenHelper.getWritableDatabase().delete(mTableName, whereClause, whereArgs);
     49         } catch (SQLiteFullException e) {
     50             onDiskFull(e);
     51         } catch (SQLiteException e) {
     52             Log.d(TAG, "Ignoring sqlite exception", e);
     53         }
     54     }
     55 
     56     /**
     57      * @see SQLiteDatabase#insertWithOnConflict(String, String, ContentValues, int)
     58      */
     59     public void insertOrReplace(ContentValues values) {
     60         if (mIgnoreWrites) {
     61             return;
     62         }
     63         try {
     64             mOpenHelper.getWritableDatabase().insertWithOnConflict(
     65                     mTableName, null, values, SQLiteDatabase.CONFLICT_REPLACE);
     66         } catch (SQLiteFullException e) {
     67             onDiskFull(e);
     68         } catch (SQLiteException e) {
     69             Log.d(TAG, "Ignoring sqlite exception", e);
     70         }
     71     }
     72 
     73     private void onDiskFull(SQLiteFullException e) {
     74         Log.e(TAG, "Disk full, all write operations will be ignored", e);
     75         mIgnoreWrites = true;
     76     }
     77 
     78     /**
     79      * @see SQLiteDatabase#query(String, String[], String, String[], String, String, String)
     80      */
     81     public Cursor query(String[] columns, String selection, String[] selectionArgs) {
     82         return mOpenHelper.getReadableDatabase().query(
     83                 mTableName, columns, selection, selectionArgs, null, null, null);
     84     }
     85 
     86     public void clear() {
     87         mOpenHelper.clearDB(mOpenHelper.getWritableDatabase());
     88     }
     89 
     90     protected abstract void onCreateTable(SQLiteDatabase db);
     91 
     92     /**
     93      * A private inner class to prevent direct DB access.
     94      */
     95     private class MySQLiteOpenHelper extends NoLocaleSQLiteHelper {
     96 
     97         public MySQLiteOpenHelper(Context context, String name, int version) {
     98             super(context, name, version);
     99         }
    100 
    101         @Override
    102         public void onCreate(SQLiteDatabase db) {
    103             onCreateTable(db);
    104         }
    105 
    106         @Override
    107         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    108             if (oldVersion != newVersion) {
    109                 clearDB(db);
    110             }
    111         }
    112 
    113         @Override
    114         public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    115             if (oldVersion != newVersion) {
    116                 clearDB(db);
    117             }
    118         }
    119 
    120         private void clearDB(SQLiteDatabase db) {
    121             db.execSQL("DROP TABLE IF EXISTS " + mTableName);
    122             onCreate(db);
    123         }
    124     }
    125 }
    126