Preventing launcher crashes due to low disk space.

In case of low disk space, all write operations to the IconCache are
silently ignored. This will not affect the Launcher behavior and
user will still see the latest icons, but in some cases, icon loading
would appear slow

Bug: 24585352
Change-Id: I85ccc519046fc3708403388bba89e019a3f2ce3d
This commit is contained in:
Sunny Goyal
2015-12-17 17:09:36 -08:00
parent d896ee43cd
commit 6f70936f7f
3 changed files with 218 additions and 129 deletions

View File

@@ -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;
@@ -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;
@@ -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";
@@ -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, " +
@@ -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) {
@@ -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) {
@@ -194,13 +169,9 @@ public class WidgetPreviewLoader {
mPackageVersions.remove(packageName);
}
try {
mDb.getWritableDatabase().delete(CacheDb.TABLE_NAME,
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);
}
mDb.delete(
CacheDb.COLUMN_PACKAGE + " = ? AND " + CacheDb.COLUMN_USER + " = ?",
new String[]{packageName, Long.toString(userSerial)});
}
/**
@@ -238,10 +209,10 @@ public class WidgetPreviewLoader {
LongSparseArray<HashSet<String>> packagesToDelete = new LongSparseArray<>();
Cursor c = null;
try {
c = mDb.getReadableDatabase().query(CacheDb.TABLE_NAME,
new String[] {CacheDb.COLUMN_USER, CacheDb.COLUMN_PACKAGE,
CacheDb.COLUMN_LAST_UPDATED, CacheDb.COLUMN_VERSION},
null, null, null, null, null);
c = mDb.query(
new String[]{CacheDb.COLUMN_USER, CacheDb.COLUMN_PACKAGE,
CacheDb.COLUMN_LAST_UPDATED, CacheDb.COLUMN_VERSION},
null, null);
while (c.moveToNext()) {
long userId = c.getLong(0);
String pkg = c.getString(1);
@@ -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();
@@ -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,
new String[] { CacheDb.COLUMN_PREVIEW_BITMAP },
CacheDb.COLUMN_COMPONENT + " = ? AND " + CacheDb.COLUMN_USER + " = ? AND " + CacheDb.COLUMN_SIZE + " = ?",
new String[] {
cursor = mDb.query(
new String[]{CacheDb.COLUMN_PREVIEW_BITMAP},
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;