diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2017-04-17 16:58:36 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2017-04-19 13:26:10 -0700 |
commit | dbfc9014feab2acad5db788f09f35723d4e4d0a1 (patch) | |
tree | 5d7c55f1616972707c0966ff5cdfc25015df4c13 /src/com | |
parent | 581a69e6d44455aba0dd1ac6a6ef266789029259 (diff) | |
download | android_packages_apps_Trebuchet-dbfc9014feab2acad5db788f09f35723d4e4d0a1.tar.gz android_packages_apps_Trebuchet-dbfc9014feab2acad5db788f09f35723d4e4d0a1.tar.bz2 android_packages_apps_Trebuchet-dbfc9014feab2acad5db788f09f35723d4e4d0a1.zip |
Simplifying some DB managed logic
> Adding SQLiteTransaction to make it easier to manage DB transactions
> Using try-with resource for better resource handling
> Defining utility method for iterating over cursor
Change-Id: I20b1a62d61798342825ecfeb971e1a0c63c9b6d7
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/launcher3/LauncherProvider.java | 173 | ||||
-rw-r--r-- | src/com/android/launcher3/provider/LauncherDbUtils.java | 61 | ||||
-rw-r--r-- | src/com/android/launcher3/provider/RestoreDbTask.java | 8 |
3 files changed, 101 insertions, 141 deletions
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 03ca24226..ca789d408 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -57,6 +57,7 @@ import com.android.launcher3.dynamicui.ExtractionUtils; import com.android.launcher3.graphics.IconShapeOverride; import com.android.launcher3.logging.FileLog; import com.android.launcher3.provider.LauncherDbUtils; +import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; import com.android.launcher3.provider.RestoreDbTask; import com.android.launcher3.util.ManagedProfileHeuristic; import com.android.launcher3.util.NoLocaleSqliteContext; @@ -70,6 +71,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedHashSet; public class LauncherProvider extends ContentProvider { private static final String TAG = "LauncherProvider"; @@ -303,8 +305,7 @@ public class LauncherProvider extends ContentProvider { SqlArguments args = new SqlArguments(uri); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { int numValues = values.length; for (int i = 0; i < numValues; i++) { addModifiedTime(values[i]); @@ -312,9 +313,7 @@ public class LauncherProvider extends ContentProvider { return 0; } } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); + t.commit(); } notifyListeners(); @@ -326,15 +325,11 @@ public class LauncherProvider extends ContentProvider { public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) throws OperationApplicationException { createDbIfNotExists(); - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(mOpenHelper.getWritableDatabase())) { ContentProviderResult[] result = super.applyBatch(operations); - db.setTransactionSuccessful(); + t.commit(); reloadLauncherIfExternal(); return result; - } finally { - db.endTransaction(); } } @@ -440,31 +435,26 @@ public class LauncherProvider extends ContentProvider { private ArrayList<Long> deleteEmptyFolders() { ArrayList<Long> folderIds = new ArrayList<>(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { // Select folders whose id do not match any container value. String selection = LauncherSettings.Favorites.ITEM_TYPE + " = " + LauncherSettings.Favorites.ITEM_TYPE_FOLDER + " AND " + LauncherSettings.Favorites._ID + " NOT IN (SELECT " + LauncherSettings.Favorites.CONTAINER + " FROM " + Favorites.TABLE_NAME + ")"; - Cursor c = db.query(Favorites.TABLE_NAME, + try (Cursor c = db.query(Favorites.TABLE_NAME, new String[] {LauncherSettings.Favorites._ID}, - selection, null, null, null, null); - while (c.moveToNext()) { - folderIds.add(c.getLong(0)); + selection, null, null, null, null)) { + LauncherDbUtils.iterateCursor(c, 0, folderIds); } - c.close(); if (!folderIds.isEmpty()) { db.delete(Favorites.TABLE_NAME, Utilities.createDbSelectionQuery( LauncherSettings.Favorites._ID, folderIds), null); } - db.setTransactionSuccessful(); + t.commit(); } catch (SQLException ex) { Log.e(TAG, ex.getMessage(), ex); folderIds.clear(); - } finally { - db.endTransaction(); } return folderIds; } @@ -718,15 +708,12 @@ public class LauncherProvider extends ContentProvider { if (oldVersion != DATA_VERSION) { // Only run the data upgrade path for an existing db. if (!Utilities.getPrefs(mContext).getBoolean(EMPTY_DATABASE_CREATED, false)) { - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { onDataUpgrade(db, oldVersion); - db.setTransactionSuccessful(); + t.commit(); } catch (Exception e) { Log.d(TAG, "Error updating data version, ignoring", e); return; - } finally { - db.endTransaction(); } } prefs.edit().putInt(PREF_KEY_DATA_VERISON, DATA_VERSION).apply(); @@ -773,35 +760,29 @@ public class LauncherProvider extends ContentProvider { addWorkspacesTable(db, false); } case 13: { - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { // Insert new column for holding widget provider name db.execSQL("ALTER TABLE favorites " + "ADD COLUMN appWidgetProvider TEXT;"); - db.setTransactionSuccessful(); + t.commit(); } catch (SQLException ex) { Log.e(TAG, ex.getMessage(), ex); // Old version remains, which means we wipe old data break; - } finally { - db.endTransaction(); } } case 14: { - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { // Insert new column for holding update timestamp db.execSQL("ALTER TABLE favorites " + "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;"); db.execSQL("ALTER TABLE workspaceScreens " + "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;"); - db.setTransactionSuccessful(); + t.commit(); } catch (SQLException ex) { Log.e(TAG, ex.getMessage(), ex); // Old version remains, which means we wipe old data break; - } finally { - db.endTransaction(); } } case 15: { @@ -884,14 +865,11 @@ public class LauncherProvider extends ContentProvider { * Clears all the data for a fresh start. */ public void createEmptyDB(SQLiteDatabase db) { - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { db.execSQL("DROP TABLE IF EXISTS " + Favorites.TABLE_NAME); db.execSQL("DROP TABLE IF EXISTS " + WorkspaceScreens.TABLE_NAME); onCreate(db); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); + t.commit(); } } @@ -911,28 +889,26 @@ public class LauncherProvider extends ContentProvider { Log.e(TAG, "getAppWidgetIds not supported", e); return; } - try { - Cursor c = db.query(Favorites.TABLE_NAME, - new String[] {Favorites.APPWIDGET_ID }, - "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null, null, null); - HashSet<Integer> validWidgets = new HashSet<>(); + final HashSet<Integer> validWidgets = new HashSet<>(); + try (Cursor c = db.query(Favorites.TABLE_NAME, + new String[] {Favorites.APPWIDGET_ID }, + "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null, null, null)) { while (c.moveToNext()) { validWidgets.add(c.getInt(0)); } - c.close(); - - for (int widgetId : allWidgets) { - if (!validWidgets.contains(widgetId)) { - try { - FileLog.d(TAG, "Deleting invalid widget " + widgetId); - host.deleteAppWidgetId(widgetId); - } catch (RuntimeException e) { - // Ignore - } - } - } } catch (SQLException ex) { Log.w(TAG, "Error getting widgets list", ex); + return; + } + for (int widgetId : allWidgets) { + if (!validWidgets.contains(widgetId)) { + try { + FileLog.d(TAG, "Deleting invalid widget " + widgetId); + host.deleteAppWidgetId(widgetId); + } catch (RuntimeException e) { + // Ignore + } + } } } @@ -941,22 +917,16 @@ public class LauncherProvider extends ContentProvider { * launcher activity target with {@link Favorites#ITEM_TYPE_APPLICATION}. */ @Thunk void convertShortcutsToLauncherActivities(SQLiteDatabase db) { - db.beginTransaction(); - Cursor c = null; - SQLiteStatement updateStmt = null; - - try { - // Only consider the primary user as other users can't have a shortcut. - long userSerial = getDefaultUserSerial(); - c = db.query(Favorites.TABLE_NAME, new String[] { - Favorites._ID, - Favorites.INTENT, - }, "itemType=" + Favorites.ITEM_TYPE_SHORTCUT + " AND profileId=" + userSerial, - null, null, null, null); - - updateStmt = db.compileStatement("UPDATE favorites SET itemType=" - + Favorites.ITEM_TYPE_APPLICATION + " WHERE _id=?"); - + try (SQLiteTransaction t = new SQLiteTransaction(db); + // Only consider the primary user as other users can't have a shortcut. + Cursor c = db.query(Favorites.TABLE_NAME, + new String[] { Favorites._ID, Favorites.INTENT}, + "itemType=" + Favorites.ITEM_TYPE_SHORTCUT + + " AND profileId=" + getDefaultUserSerial(), + null, null, null, null); + SQLiteStatement updateStmt = db.compileStatement("UPDATE favorites SET itemType=" + + Favorites.ITEM_TYPE_APPLICATION + " WHERE _id=?") + ) { final int idIndex = c.getColumnIndexOrThrow(Favorites._ID); final int intentIndex = c.getColumnIndexOrThrow(Favorites.INTENT); @@ -978,17 +948,9 @@ public class LauncherProvider extends ContentProvider { updateStmt.bindLong(1, id); updateStmt.executeUpdateDelete(); } - db.setTransactionSuccessful(); + t.commit(); } catch (SQLException ex) { Log.w(TAG, "Error deduping shortcuts", ex); - } finally { - db.endTransaction(); - if (c != null) { - c.close(); - } - if (updateStmt != null) { - updateStmt.close(); - } } } @@ -996,26 +958,17 @@ public class LauncherProvider extends ContentProvider { * Recreates workspace table and migrates data to the new table. */ public boolean recreateWorkspaceTable(SQLiteDatabase db) { - db.beginTransaction(); - try { - Cursor c = db.query(WorkspaceScreens.TABLE_NAME, + try (SQLiteTransaction t = new SQLiteTransaction(db)) { + final ArrayList<Long> sortedIDs; + + try (Cursor c = db.query(WorkspaceScreens.TABLE_NAME, new String[] {LauncherSettings.WorkspaceScreens._ID}, null, null, null, null, - LauncherSettings.WorkspaceScreens.SCREEN_RANK); - ArrayList<Long> sortedIDs = new ArrayList<Long>(); - long maxId = 0; - try { - while (c.moveToNext()) { - Long id = c.getLong(0); - if (!sortedIDs.contains(id)) { - sortedIDs.add(id); - maxId = Math.max(maxId, id); - } - } - } finally { - c.close(); + LauncherSettings.WorkspaceScreens.SCREEN_RANK)) { + // Use LinkedHashSet so that ordering is preserved + sortedIDs = new ArrayList<>( + LauncherDbUtils.iterateCursor(c, 0, new LinkedHashSet<Long>())); } - db.execSQL("DROP TABLE IF EXISTS " + WorkspaceScreens.TABLE_NAME); addWorkspacesTable(db, false); @@ -1028,21 +981,18 @@ public class LauncherProvider extends ContentProvider { addModifiedTime(values); db.insertOrThrow(WorkspaceScreens.TABLE_NAME, null, values); } - db.setTransactionSuccessful(); - mMaxScreenId = maxId; + t.commit(); + mMaxScreenId = sortedIDs.isEmpty() ? 0 : Collections.max(sortedIDs); } catch (SQLException ex) { // Old version remains, which means we wipe old data Log.e(TAG, ex.getMessage(), ex); return false; - } finally { - db.endTransaction(); } return true; } @Thunk boolean updateFolderItemsRank(SQLiteDatabase db, boolean addRankColumn) { - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { if (addRankColumn) { // Insert new column for holding rank db.execSQL("ALTER TABLE favorites ADD COLUMN rank INTEGER NOT NULL DEFAULT 0;"); @@ -1061,13 +1011,11 @@ public class LauncherProvider extends ContentProvider { } c.close(); - db.setTransactionSuccessful(); + t.commit(); } catch (SQLException ex) { // Old version remains, which means we wipe old data Log.e(TAG, ex.getMessage(), ex); return false; - } finally { - db.endTransaction(); } return true; } @@ -1077,16 +1025,13 @@ public class LauncherProvider extends ContentProvider { } private boolean addIntegerColumn(SQLiteDatabase db, String columnName, long defaultValue) { - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { db.execSQL("ALTER TABLE favorites ADD COLUMN " + columnName + " INTEGER NOT NULL DEFAULT " + defaultValue + ";"); - db.setTransactionSuccessful(); + t.commit(); } catch (SQLException ex) { Log.e(TAG, ex.getMessage(), ex); return false; - } finally { - db.endTransaction(); } return true; } diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java index 175835011..632504060 100644 --- a/src/com/android/launcher3/provider/LauncherDbUtils.java +++ b/src/com/android/launcher3/provider/LauncherDbUtils.java @@ -19,15 +19,16 @@ package com.android.launcher3.provider; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; +import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; import android.util.Log; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.LauncherSettings.WorkspaceScreens; -import com.android.launcher3.logging.FileLog; import java.util.ArrayList; +import java.util.Collection; /** * A set of utility methods for Launcher DB used for DB updates and migration. @@ -44,8 +45,7 @@ public class LauncherDbUtils { * items are simply deleted. */ public static boolean prepareScreenZeroToHostQsb(Context context, SQLiteDatabase db) { - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { // Get the existing screens ArrayList<Long> screenIds = getScreenIdsFromCursor(db.query(WorkspaceScreens.TABLE_NAME, null, null, null, null, null, WorkspaceScreens.SCREEN_RANK)); @@ -68,23 +68,19 @@ public class LauncherDbUtils { } // Check if the first row is empty - try (Cursor c = db.query(Favorites.TABLE_NAME, null, - "container = -100 and screen = 0 and cellY = 0", null, null, null, null)) { - if (c.getCount() == 0) { - // First row is empty, no need to migrate. - return true; - } + if (DatabaseUtils.queryNumEntries(db, Favorites.TABLE_NAME, + "container = -100 and screen = 0 and cellY = 0") == 0) { + // First row is empty, no need to migrate. + return true; } new LossyScreenMigrationTask(context, LauncherAppState.getIDP(context), db) .migrateScreen0(); - db.setTransactionSuccessful(); + t.commit(); return true; } catch (Exception e) { Log.e(TAG, "Failed to update workspace size", e); return false; - } finally { - db.endTransaction(); } } @@ -104,19 +100,40 @@ public class LauncherDbUtils { * Parses the cursor containing workspace screens table and returns the list of screen IDs */ public static ArrayList<Long> getScreenIdsFromCursor(Cursor sc) { - ArrayList<Long> screenIds = new ArrayList<Long>(); try { - final int idIndex = sc.getColumnIndexOrThrow(WorkspaceScreens._ID); - while (sc.moveToNext()) { - try { - screenIds.add(sc.getLong(idIndex)); - } catch (Exception e) { - FileLog.d(TAG, "Invalid screen id", e); - } - } + return iterateCursor(sc, + sc.getColumnIndexOrThrow(WorkspaceScreens._ID), + new ArrayList<Long>()); } finally { sc.close(); } - return screenIds; + } + + public static <T extends Collection<Long>> T iterateCursor(Cursor c, int columnIndex, T out) { + while (c.moveToNext()) { + out.add(c.getLong(columnIndex)); + } + return out; + } + + /** + * Utility class to simplify managing sqlite transactions + */ + public static class SQLiteTransaction implements AutoCloseable { + private final SQLiteDatabase mDb; + + public SQLiteTransaction(SQLiteDatabase db) { + mDb = db; + db.beginTransaction(); + } + + public void commit() { + mDb.setTransactionSuccessful(); + } + + @Override + public void close() { + mDb.endTransaction(); + } } } diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index dc85abad7..00e2644a5 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -27,6 +27,7 @@ import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.ShortcutInfo; import com.android.launcher3.Utilities; import com.android.launcher3.logging.FileLog; +import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; import com.android.launcher3.util.LogConfig; import java.io.InvalidObjectException; @@ -47,16 +48,13 @@ public class RestoreDbTask { public static boolean performRestore(DatabaseHelper helper) { SQLiteDatabase db = helper.getWritableDatabase(); - db.beginTransaction(); - try { + try (SQLiteTransaction t = new SQLiteTransaction(db)) { new RestoreDbTask().sanitizeDB(helper, db); - db.setTransactionSuccessful(); + t.commit(); return true; } catch (Exception e) { FileLog.e(TAG, "Failed to verify db", e); return false; - } finally { - db.endTransaction(); } } |