Loading src/com/android/launcher3/IconCache.java +71 −80 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; Loading @@ -48,6 +48,7 @@ import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.PackageItemInfo; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.SQLiteCacheHelper; import com.android.launcher3.util.Thunk; import java.util.Collections; Loading Loading @@ -230,7 +231,7 @@ public class IconCache { public synchronized void removeIconsForPkg(String packageName, UserHandleCompat user) { removeFromMemCacheLocked(packageName, user); long userSerial = mUserManager.getSerialNumberForUser(user); mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME, mIconDb.delete( IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?", new String[]{packageName + "/%", Long.toString(userSerial)}); } Loading Loading @@ -275,13 +276,17 @@ public class IconCache { componentMap.put(app.getComponentName(), app); } Cursor c = mIconDb.getReadableDatabase().query(IconDB.TABLE_NAME, HashSet<Integer> itemsToRemove = new HashSet<Integer>(); Stack<LauncherActivityInfoCompat> appsToUpdate = new Stack<>(); Cursor c = null; try { c = mIconDb.query( new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT, IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION, IconDB.COLUMN_SYSTEM_STATE}, IconDB.COLUMN_USER + " = ? ", new String[] {Long.toString(userSerial)}, null, null, null); new String[]{Long.toString(userSerial)}); final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT); final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED); Loading @@ -289,9 +294,6 @@ public class IconCache { final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID); final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE); HashSet<Integer> itemsToRemove = new HashSet<Integer>(); Stack<LauncherActivityInfoCompat> appsToUpdate = new Stack<>(); while (c.moveToNext()) { String cn = c.getString(indexComponent); ComponentName component = ComponentName.unflattenFromString(cn); Loading Loading @@ -322,11 +324,17 @@ public class IconCache { appsToUpdate.add(app); } } } catch (SQLiteException e) { Log.d(TAG, "Error reading icon cache", e); // Continue updating whatever we have read so far } finally { if (c != null) { c.close(); } } if (!itemsToRemove.isEmpty()) { mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME, Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null); mIconDb.delete( Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null); } // Insert remaining apps. Loading Loading @@ -356,8 +364,7 @@ public class IconCache { values.put(IconDB.COLUMN_USER, userSerial); values.put(IconDB.COLUMN_LAST_UPDATED, info.lastUpdateTime); values.put(IconDB.COLUMN_VERSION, info.versionCode); mIconDb.getWritableDatabase().insertWithOnConflict(IconDB.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); mIconDb.insertOrReplace(values); } @Thunk ContentValues updateCacheAndGetContentValues(LauncherActivityInfoCompat app, Loading Loading @@ -672,19 +679,18 @@ public class IconCache { label, Color.TRANSPARENT); values.put(IconDB.COLUMN_COMPONENT, componentName.flattenToString()); values.put(IconDB.COLUMN_USER, userSerial); mIconDb.getWritableDatabase().insertWithOnConflict(IconDB.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); mIconDb.insertOrReplace(values); } private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) { Cursor c = mIconDb.getReadableDatabase().query(IconDB.TABLE_NAME, Cursor c = null; try { c = mIconDb.query( new String[]{lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON, IconDB.COLUMN_LABEL}, IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?", new String[]{cacheKey.componentName.flattenToString(), Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))}, null, null, null); try { Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))}); if (c.moveToNext()) { entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : null); entry.isLowResIcon = lowRes; Loading @@ -698,9 +704,13 @@ public class IconCache { } return true; } } catch (SQLiteException e) { Log.d(TAG, "Error reading icon cache", e); } finally { if (c != null) { c.close(); } } return false; } Loading Loading @@ -745,7 +755,7 @@ public class IconCache { LauncherActivityInfoCompat app = mAppsToUpdate.pop(); String cn = app.getComponentName().flattenToString(); ContentValues values = updateCacheAndGetContentValues(app, true); mIconDb.getWritableDatabase().update(IconDB.TABLE_NAME, values, mIconDb.update(values, IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?", new String[]{cn, Long.toString(mUserSerial)}); mUpdatedPackages.add(app.getComponentName().getPackageName()); Loading Loading @@ -782,7 +792,7 @@ public class IconCache { mSystemState = Locale.getDefault().toString(); } private static final class IconDB extends SQLiteOpenHelper { private static final class IconDB extends SQLiteCacheHelper { private final static int DB_VERSION = 7; private final static int RELEASE_VERSION = DB_VERSION + Loading @@ -800,11 +810,11 @@ public class IconCache { private final static String COLUMN_SYSTEM_STATE = "system_state"; public IconDB(Context context) { super(context, LauncherFiles.APP_ICONS_DB, null, RELEASE_VERSION); super(context, LauncherFiles.APP_ICONS_DB, RELEASE_VERSION, TABLE_NAME); } @Override public void onCreate(SQLiteDatabase db) { protected void onCreateTable(SQLiteDatabase db) { db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + COLUMN_COMPONENT + " TEXT NOT NULL, " + COLUMN_USER + " INTEGER NOT NULL, " + Loading @@ -817,25 +827,6 @@ public class IconCache { "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ") " + ");"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } private void clearDB(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } } private ContentValues newContentValues(Bitmap icon, String label, int lowResBackgroundColor) { Loading src/com/android/launcher3/WidgetPreviewLoader.java +19 −49 Original line number Diff line number Diff line Loading @@ -10,7 +10,6 @@ import android.content.res.Resources; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; Loading @@ -32,6 +31,7 @@ import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.SQLiteCacheHelper; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.WidgetCell; Loading Loading @@ -104,7 +104,7 @@ public class WidgetPreviewLoader { * The DB holds the generated previews for various components. Previews can also have different * sizes (landscape vs portrait). */ private static class CacheDb extends SQLiteOpenHelper { private static class CacheDb extends SQLiteCacheHelper { private static final int DB_VERSION = 4; private static final String TABLE_NAME = "shortcut_and_widget_previews"; Loading @@ -117,11 +117,11 @@ public class WidgetPreviewLoader { private static final String COLUMN_PREVIEW_BITMAP = "preview_bitmap"; public CacheDb(Context context) { super(context, LauncherFiles.WIDGET_PREVIEWS_DB, null, DB_VERSION); super(context, LauncherFiles.WIDGET_PREVIEWS_DB, DB_VERSION, TABLE_NAME); } @Override public void onCreate(SQLiteDatabase database) { public void onCreateTable(SQLiteDatabase database) { database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + COLUMN_COMPONENT + " TEXT NOT NULL, " + COLUMN_USER + " INTEGER NOT NULL, " + Loading @@ -133,25 +133,6 @@ public class WidgetPreviewLoader { "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ", " + COLUMN_SIZE + ") " + ");"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } private void clearDB(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } } private WidgetCacheKey getObjectKey(Object o, String size) { Loading @@ -176,13 +157,7 @@ public class WidgetPreviewLoader { values.put(CacheDb.COLUMN_VERSION, versions[0]); values.put(CacheDb.COLUMN_LAST_UPDATED, versions[1]); values.put(CacheDb.COLUMN_PREVIEW_BITMAP, Utilities.flattenBitmap(preview)); try { mDb.getWritableDatabase().insertWithOnConflict(CacheDb.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); } catch (SQLException e) { Log.e(TAG, "Error saving image to DB", e); } mDb.insertOrReplace(values); } public void removePackage(String packageName, UserHandleCompat user) { Loading @@ -194,13 +169,9 @@ public class WidgetPreviewLoader { mPackageVersions.remove(packageName); } try { mDb.getWritableDatabase().delete(CacheDb.TABLE_NAME, mDb.delete( CacheDb.COLUMN_PACKAGE + " = ? AND " + CacheDb.COLUMN_USER + " = ?", new String[]{packageName, Long.toString(userSerial)}); } catch (SQLException e) { Log.e(TAG, "Unable to delete items from DB", e); } } /** Loading Loading @@ -238,10 +209,10 @@ public class WidgetPreviewLoader { LongSparseArray<HashSet<String>> packagesToDelete = new LongSparseArray<>(); Cursor c = null; try { c = mDb.getReadableDatabase().query(CacheDb.TABLE_NAME, c = mDb.query( new String[]{CacheDb.COLUMN_USER, CacheDb.COLUMN_PACKAGE, CacheDb.COLUMN_LAST_UPDATED, CacheDb.COLUMN_VERSION}, null, null, null, null, null); null, null); while (c.moveToNext()) { long userId = c.getLong(0); String pkg = c.getString(1); Loading Loading @@ -274,7 +245,7 @@ public class WidgetPreviewLoader { } } } catch (SQLException e) { Log.e(TAG, "Error updatating widget previews", e); Log.e(TAG, "Error updating widget previews", e); } finally { if (c != null) { c.close(); Loading @@ -288,16 +259,15 @@ public class WidgetPreviewLoader { @Thunk Bitmap readFromDb(WidgetCacheKey key, Bitmap recycle, PreviewLoadTask loadTask) { Cursor cursor = null; try { cursor = mDb.getReadableDatabase().query( CacheDb.TABLE_NAME, cursor = mDb.query( new String[]{CacheDb.COLUMN_PREVIEW_BITMAP}, CacheDb.COLUMN_COMPONENT + " = ? AND " + CacheDb.COLUMN_USER + " = ? AND " + CacheDb.COLUMN_SIZE + " = ?", CacheDb.COLUMN_COMPONENT + " = ? AND " + CacheDb.COLUMN_USER + " = ? AND " + CacheDb.COLUMN_SIZE + " = ?", new String[]{ key.componentName.flattenToString(), Long.toString(mUserManager.getSerialNumberForUser(key.user)), key.size }, null, null, null); }); // If cancelled, skip getting the blob and decoding it into a bitmap if (loadTask.isCancelled()) { return null; Loading src/com/android/launcher3/util/SQLiteCacheHelper.java 0 → 100644 +128 −0 Original line number Diff line number Diff line package com.android.launcher3.util; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteFullException; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; /** * An extension of {@link SQLiteOpenHelper} with utility methods for a single table cache DB. * Any exception during write operations are ignored, and any version change causes a DB reset. */ public abstract class SQLiteCacheHelper { private static final String TAG = "SQLiteCacheHelper"; private final String mTableName; private final MySQLiteOpenHelper mOpenHelper; private boolean mIgnoreWrites; public SQLiteCacheHelper(Context context, String name, int version, String tableName) { mTableName = tableName; mOpenHelper = new MySQLiteOpenHelper(context, name, version); mIgnoreWrites = false; } /** * @see SQLiteDatabase#update(String, ContentValues, String, String[]) */ public void update(ContentValues values, String whereClause, String[] whereArgs) { if (mIgnoreWrites) { return; } try { mOpenHelper.getWritableDatabase().update(mTableName, values, whereClause, whereArgs); } catch (SQLiteFullException e) { onDiskFull(e); } catch (SQLiteException e) { Log.d(TAG, "Ignoring sqlite exception", e); } } /** * @see SQLiteDatabase#delete(String, String, String[]) */ public void delete(String whereClause, String[] whereArgs) { if (mIgnoreWrites) { return; } try { mOpenHelper.getWritableDatabase().delete(mTableName, whereClause, whereArgs); } catch (SQLiteFullException e) { onDiskFull(e); } catch (SQLiteException e) { Log.d(TAG, "Ignoring sqlite exception", e); } } /** * @see SQLiteDatabase#insertWithOnConflict(String, String, ContentValues, int) */ public void insertOrReplace(ContentValues values) { if (mIgnoreWrites) { return; } try { mOpenHelper.getWritableDatabase().insertWithOnConflict( mTableName, null, values, SQLiteDatabase.CONFLICT_REPLACE); } catch (SQLiteFullException e) { onDiskFull(e); } catch (SQLiteException e) { Log.d(TAG, "Ignoring sqlite exception", e); } } private void onDiskFull(SQLiteFullException e) { Log.e(TAG, "Disk full, all write operations will be ignored", e); mIgnoreWrites = true; } /** * @see SQLiteDatabase#query(String, String[], String, String[], String, String, String) */ public Cursor query(String[] columns, String selection, String[] selectionArgs) { return mOpenHelper.getReadableDatabase().query( mTableName, columns, selection, selectionArgs, null, null, null); } protected abstract void onCreateTable(SQLiteDatabase db); /** * A private inner class to prevent direct DB access. */ private class MySQLiteOpenHelper extends SQLiteOpenHelper { public MySQLiteOpenHelper(Context context, String name, int version) { super(context, name, null, version); } @Override public void onCreate(SQLiteDatabase db) { onCreateTable(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } private void clearDB(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + mTableName); onCreate(db); } } } Loading
src/com/android/launcher3/IconCache.java +71 −80 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; Loading @@ -48,6 +48,7 @@ import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.PackageItemInfo; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.SQLiteCacheHelper; import com.android.launcher3.util.Thunk; import java.util.Collections; Loading Loading @@ -230,7 +231,7 @@ public class IconCache { public synchronized void removeIconsForPkg(String packageName, UserHandleCompat user) { removeFromMemCacheLocked(packageName, user); long userSerial = mUserManager.getSerialNumberForUser(user); mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME, mIconDb.delete( IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?", new String[]{packageName + "/%", Long.toString(userSerial)}); } Loading Loading @@ -275,13 +276,17 @@ public class IconCache { componentMap.put(app.getComponentName(), app); } Cursor c = mIconDb.getReadableDatabase().query(IconDB.TABLE_NAME, HashSet<Integer> itemsToRemove = new HashSet<Integer>(); Stack<LauncherActivityInfoCompat> appsToUpdate = new Stack<>(); Cursor c = null; try { c = mIconDb.query( new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT, IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION, IconDB.COLUMN_SYSTEM_STATE}, IconDB.COLUMN_USER + " = ? ", new String[] {Long.toString(userSerial)}, null, null, null); new String[]{Long.toString(userSerial)}); final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT); final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED); Loading @@ -289,9 +294,6 @@ public class IconCache { final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID); final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE); HashSet<Integer> itemsToRemove = new HashSet<Integer>(); Stack<LauncherActivityInfoCompat> appsToUpdate = new Stack<>(); while (c.moveToNext()) { String cn = c.getString(indexComponent); ComponentName component = ComponentName.unflattenFromString(cn); Loading Loading @@ -322,11 +324,17 @@ public class IconCache { appsToUpdate.add(app); } } } catch (SQLiteException e) { Log.d(TAG, "Error reading icon cache", e); // Continue updating whatever we have read so far } finally { if (c != null) { c.close(); } } if (!itemsToRemove.isEmpty()) { mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME, Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null); mIconDb.delete( Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null); } // Insert remaining apps. Loading Loading @@ -356,8 +364,7 @@ public class IconCache { values.put(IconDB.COLUMN_USER, userSerial); values.put(IconDB.COLUMN_LAST_UPDATED, info.lastUpdateTime); values.put(IconDB.COLUMN_VERSION, info.versionCode); mIconDb.getWritableDatabase().insertWithOnConflict(IconDB.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); mIconDb.insertOrReplace(values); } @Thunk ContentValues updateCacheAndGetContentValues(LauncherActivityInfoCompat app, Loading Loading @@ -672,19 +679,18 @@ public class IconCache { label, Color.TRANSPARENT); values.put(IconDB.COLUMN_COMPONENT, componentName.flattenToString()); values.put(IconDB.COLUMN_USER, userSerial); mIconDb.getWritableDatabase().insertWithOnConflict(IconDB.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); mIconDb.insertOrReplace(values); } private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) { Cursor c = mIconDb.getReadableDatabase().query(IconDB.TABLE_NAME, Cursor c = null; try { c = mIconDb.query( new String[]{lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON, IconDB.COLUMN_LABEL}, IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?", new String[]{cacheKey.componentName.flattenToString(), Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))}, null, null, null); try { Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))}); if (c.moveToNext()) { entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : null); entry.isLowResIcon = lowRes; Loading @@ -698,9 +704,13 @@ public class IconCache { } return true; } } catch (SQLiteException e) { Log.d(TAG, "Error reading icon cache", e); } finally { if (c != null) { c.close(); } } return false; } Loading Loading @@ -745,7 +755,7 @@ public class IconCache { LauncherActivityInfoCompat app = mAppsToUpdate.pop(); String cn = app.getComponentName().flattenToString(); ContentValues values = updateCacheAndGetContentValues(app, true); mIconDb.getWritableDatabase().update(IconDB.TABLE_NAME, values, mIconDb.update(values, IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?", new String[]{cn, Long.toString(mUserSerial)}); mUpdatedPackages.add(app.getComponentName().getPackageName()); Loading Loading @@ -782,7 +792,7 @@ public class IconCache { mSystemState = Locale.getDefault().toString(); } private static final class IconDB extends SQLiteOpenHelper { private static final class IconDB extends SQLiteCacheHelper { private final static int DB_VERSION = 7; private final static int RELEASE_VERSION = DB_VERSION + Loading @@ -800,11 +810,11 @@ public class IconCache { private final static String COLUMN_SYSTEM_STATE = "system_state"; public IconDB(Context context) { super(context, LauncherFiles.APP_ICONS_DB, null, RELEASE_VERSION); super(context, LauncherFiles.APP_ICONS_DB, RELEASE_VERSION, TABLE_NAME); } @Override public void onCreate(SQLiteDatabase db) { protected void onCreateTable(SQLiteDatabase db) { db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + COLUMN_COMPONENT + " TEXT NOT NULL, " + COLUMN_USER + " INTEGER NOT NULL, " + Loading @@ -817,25 +827,6 @@ public class IconCache { "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ") " + ");"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } private void clearDB(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } } private ContentValues newContentValues(Bitmap icon, String label, int lowResBackgroundColor) { Loading
src/com/android/launcher3/WidgetPreviewLoader.java +19 −49 Original line number Diff line number Diff line Loading @@ -10,7 +10,6 @@ import android.content.res.Resources; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; Loading @@ -32,6 +31,7 @@ import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.SQLiteCacheHelper; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.WidgetCell; Loading Loading @@ -104,7 +104,7 @@ public class WidgetPreviewLoader { * The DB holds the generated previews for various components. Previews can also have different * sizes (landscape vs portrait). */ private static class CacheDb extends SQLiteOpenHelper { private static class CacheDb extends SQLiteCacheHelper { private static final int DB_VERSION = 4; private static final String TABLE_NAME = "shortcut_and_widget_previews"; Loading @@ -117,11 +117,11 @@ public class WidgetPreviewLoader { private static final String COLUMN_PREVIEW_BITMAP = "preview_bitmap"; public CacheDb(Context context) { super(context, LauncherFiles.WIDGET_PREVIEWS_DB, null, DB_VERSION); super(context, LauncherFiles.WIDGET_PREVIEWS_DB, DB_VERSION, TABLE_NAME); } @Override public void onCreate(SQLiteDatabase database) { public void onCreateTable(SQLiteDatabase database) { database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + COLUMN_COMPONENT + " TEXT NOT NULL, " + COLUMN_USER + " INTEGER NOT NULL, " + Loading @@ -133,25 +133,6 @@ public class WidgetPreviewLoader { "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ", " + COLUMN_SIZE + ") " + ");"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } private void clearDB(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } } private WidgetCacheKey getObjectKey(Object o, String size) { Loading @@ -176,13 +157,7 @@ public class WidgetPreviewLoader { values.put(CacheDb.COLUMN_VERSION, versions[0]); values.put(CacheDb.COLUMN_LAST_UPDATED, versions[1]); values.put(CacheDb.COLUMN_PREVIEW_BITMAP, Utilities.flattenBitmap(preview)); try { mDb.getWritableDatabase().insertWithOnConflict(CacheDb.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); } catch (SQLException e) { Log.e(TAG, "Error saving image to DB", e); } mDb.insertOrReplace(values); } public void removePackage(String packageName, UserHandleCompat user) { Loading @@ -194,13 +169,9 @@ public class WidgetPreviewLoader { mPackageVersions.remove(packageName); } try { mDb.getWritableDatabase().delete(CacheDb.TABLE_NAME, mDb.delete( CacheDb.COLUMN_PACKAGE + " = ? AND " + CacheDb.COLUMN_USER + " = ?", new String[]{packageName, Long.toString(userSerial)}); } catch (SQLException e) { Log.e(TAG, "Unable to delete items from DB", e); } } /** Loading Loading @@ -238,10 +209,10 @@ public class WidgetPreviewLoader { LongSparseArray<HashSet<String>> packagesToDelete = new LongSparseArray<>(); Cursor c = null; try { c = mDb.getReadableDatabase().query(CacheDb.TABLE_NAME, c = mDb.query( new String[]{CacheDb.COLUMN_USER, CacheDb.COLUMN_PACKAGE, CacheDb.COLUMN_LAST_UPDATED, CacheDb.COLUMN_VERSION}, null, null, null, null, null); null, null); while (c.moveToNext()) { long userId = c.getLong(0); String pkg = c.getString(1); Loading Loading @@ -274,7 +245,7 @@ public class WidgetPreviewLoader { } } } catch (SQLException e) { Log.e(TAG, "Error updatating widget previews", e); Log.e(TAG, "Error updating widget previews", e); } finally { if (c != null) { c.close(); Loading @@ -288,16 +259,15 @@ public class WidgetPreviewLoader { @Thunk Bitmap readFromDb(WidgetCacheKey key, Bitmap recycle, PreviewLoadTask loadTask) { Cursor cursor = null; try { cursor = mDb.getReadableDatabase().query( CacheDb.TABLE_NAME, cursor = mDb.query( new String[]{CacheDb.COLUMN_PREVIEW_BITMAP}, CacheDb.COLUMN_COMPONENT + " = ? AND " + CacheDb.COLUMN_USER + " = ? AND " + CacheDb.COLUMN_SIZE + " = ?", CacheDb.COLUMN_COMPONENT + " = ? AND " + CacheDb.COLUMN_USER + " = ? AND " + CacheDb.COLUMN_SIZE + " = ?", new String[]{ key.componentName.flattenToString(), Long.toString(mUserManager.getSerialNumberForUser(key.user)), key.size }, null, null, null); }); // If cancelled, skip getting the blob and decoding it into a bitmap if (loadTask.isCancelled()) { return null; Loading
src/com/android/launcher3/util/SQLiteCacheHelper.java 0 → 100644 +128 −0 Original line number Diff line number Diff line package com.android.launcher3.util; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteFullException; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; /** * An extension of {@link SQLiteOpenHelper} with utility methods for a single table cache DB. * Any exception during write operations are ignored, and any version change causes a DB reset. */ public abstract class SQLiteCacheHelper { private static final String TAG = "SQLiteCacheHelper"; private final String mTableName; private final MySQLiteOpenHelper mOpenHelper; private boolean mIgnoreWrites; public SQLiteCacheHelper(Context context, String name, int version, String tableName) { mTableName = tableName; mOpenHelper = new MySQLiteOpenHelper(context, name, version); mIgnoreWrites = false; } /** * @see SQLiteDatabase#update(String, ContentValues, String, String[]) */ public void update(ContentValues values, String whereClause, String[] whereArgs) { if (mIgnoreWrites) { return; } try { mOpenHelper.getWritableDatabase().update(mTableName, values, whereClause, whereArgs); } catch (SQLiteFullException e) { onDiskFull(e); } catch (SQLiteException e) { Log.d(TAG, "Ignoring sqlite exception", e); } } /** * @see SQLiteDatabase#delete(String, String, String[]) */ public void delete(String whereClause, String[] whereArgs) { if (mIgnoreWrites) { return; } try { mOpenHelper.getWritableDatabase().delete(mTableName, whereClause, whereArgs); } catch (SQLiteFullException e) { onDiskFull(e); } catch (SQLiteException e) { Log.d(TAG, "Ignoring sqlite exception", e); } } /** * @see SQLiteDatabase#insertWithOnConflict(String, String, ContentValues, int) */ public void insertOrReplace(ContentValues values) { if (mIgnoreWrites) { return; } try { mOpenHelper.getWritableDatabase().insertWithOnConflict( mTableName, null, values, SQLiteDatabase.CONFLICT_REPLACE); } catch (SQLiteFullException e) { onDiskFull(e); } catch (SQLiteException e) { Log.d(TAG, "Ignoring sqlite exception", e); } } private void onDiskFull(SQLiteFullException e) { Log.e(TAG, "Disk full, all write operations will be ignored", e); mIgnoreWrites = true; } /** * @see SQLiteDatabase#query(String, String[], String, String[], String, String, String) */ public Cursor query(String[] columns, String selection, String[] selectionArgs) { return mOpenHelper.getReadableDatabase().query( mTableName, columns, selection, selectionArgs, null, null, null); } protected abstract void onCreateTable(SQLiteDatabase db); /** * A private inner class to prevent direct DB access. */ private class MySQLiteOpenHelper extends SQLiteOpenHelper { public MySQLiteOpenHelper(Context context, String name, int version) { super(context, name, null, version); } @Override public void onCreate(SQLiteDatabase db) { onCreateTable(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion != newVersion) { clearDB(db); } } private void clearDB(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + mTableName); onCreate(db); } } }