/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package xyz.klinker.blur.launcher3.provider; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.util.Log; import xyz.klinker.blur.launcher3.LauncherAppState; import xyz.klinker.blur.launcher3.LauncherSettings.Favorites; import xyz.klinker.blur.launcher3.LauncherSettings.WorkspaceScreens; import xyz.klinker.blur.launcher3.logging.FileLog; import java.util.ArrayList; /** * A set of utility methods for Launcher DB used for DB updates and migration. */ public class LauncherDbUtils { private static final String TAG = "LauncherDbUtils"; /** * Makes the first screen as screen 0 (if screen 0 already exists, * renames it to some other number). * If the first row of screen 0 is non empty, runs a 'lossy' GridMigrationTask to clear * the first row. The items in the first screen are moved and resized but the carry-forward * items are simply deleted. */ public static boolean prepareScreenZeroToHostQsb(SQLiteDatabase db) { db.beginTransaction(); try { // Get the existing screens ArrayList<Long> screenIds = getScreenIdsFromCursor(db.query(WorkspaceScreens.TABLE_NAME, null, null, null, null, null, WorkspaceScreens.SCREEN_RANK)); if (screenIds.isEmpty()) { // No update needed return true; } if (screenIds.get(0) != 0) { // First screen is not 0, we need to rename screens if (screenIds.indexOf(0L) > -1) { // There is already a screen 0. First rename it to a differen screen. long newScreenId = 1; while (screenIds.indexOf(newScreenId) > -1) newScreenId++; renameScreen(db, 0, newScreenId); } // Rename the first screen to 0. renameScreen(db, screenIds.get(0), 0); } // 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; } } LauncherAppState app = LauncherAppState.getInstance(); new LossyScreenMigrationTask(app.getContext(), app.getInvariantDeviceProfile(), db) .migrateScreen0(); db.setTransactionSuccessful(); return true; } catch (Exception e) { Log.e(TAG, "Failed to update workspace size", e); return false; } finally { db.endTransaction(); } } private static void renameScreen(SQLiteDatabase db, long oldScreen, long newScreen) { String[] whereParams = new String[] { Long.toString(oldScreen) }; ContentValues values = new ContentValues(); values.put(WorkspaceScreens._ID, newScreen); db.update(WorkspaceScreens.TABLE_NAME, values, "_id = ?", whereParams); values.clear(); values.put(Favorites.SCREEN, newScreen); db.update(Favorites.TABLE_NAME, values, "container = -100 and screen = ?", whereParams); } /** * 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); } } } finally { sc.close(); } return screenIds; } }