diff options
Diffstat (limited to 'src/com/android/launcher3/LauncherProvider.java')
-rw-r--r-- | src/com/android/launcher3/LauncherProvider.java | 496 |
1 files changed, 280 insertions, 216 deletions
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 1040b1173..b5901265c 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -16,6 +16,7 @@ package com.android.launcher3; +import android.annotation.TargetApi; import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetManager; import android.content.ComponentName; @@ -29,14 +30,19 @@ import android.content.Context; import android.content.Intent; import android.content.OperationApplicationException; import android.content.SharedPreferences; +import android.content.pm.PackageManager.NameNotFoundException; 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.database.sqlite.SQLiteQueryBuilder; +import android.database.sqlite.SQLiteStatement; import android.net.Uri; +import android.os.Build; +import android.os.Bundle; import android.os.StrictMode; +import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; @@ -46,6 +52,8 @@ import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.ProviderConfig; +import com.android.launcher3.util.ManagedProfileHeuristic; +import com.android.launcher3.util.Thunk; import java.io.File; import java.net.URISyntaxException; @@ -57,20 +65,19 @@ public class LauncherProvider extends ContentProvider { private static final String TAG = "Launcher.LauncherProvider"; private static final boolean LOGD = false; - private static final int MIN_DATABASE_VERSION = 12; - private static final int DATABASE_VERSION = 22; + private static final int DATABASE_VERSION = 26; static final String OLD_AUTHORITY = "com.android.launcher2.settings"; static final String AUTHORITY = ProviderConfig.AUTHORITY; - static final String TABLE_FAVORITES = "favorites"; - static final String TABLE_WORKSPACE_SCREENS = "workspaceScreens"; - static final String PARAMETER_NOTIFY = "notify"; - static final String UPGRADED_FROM_OLD_DATABASE = "UPGRADED_FROM_OLD_DATABASE"; + static final String TABLE_FAVORITES = LauncherSettings.Favorites.TABLE_NAME; + static final String TABLE_WORKSPACE_SCREENS = LauncherSettings.WorkspaceScreens.TABLE_NAME; static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED"; private static final String URI_PARAM_IS_EXTERNAL_ADD = "isExternalAdd"; + private static final String RESTRICTION_PACKAGE_NAME = "workspace.configuration.package.name"; + private LauncherProviderChangeListener mListener; /** @@ -81,7 +88,7 @@ public class LauncherProvider extends ContentProvider { static final Uri CONTENT_APPWIDGET_RESET_URI = Uri.parse("content://" + AUTHORITY + "/appWidgetReset"); - private DatabaseHelper mOpenHelper; + @Thunk DatabaseHelper mOpenHelper; @Override public boolean onCreate() { @@ -126,7 +133,7 @@ public class LauncherProvider extends ContentProvider { return result; } - private static long dbInsertAndCheck(DatabaseHelper helper, + @Thunk static long dbInsertAndCheck(DatabaseHelper helper, SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) { if (values == null) { throw new RuntimeException("Error: attempting to insert null values"); @@ -144,7 +151,8 @@ public class LauncherProvider extends ContentProvider { // In very limited cases, we support system|signature permission apps to add to the db String externalAdd = uri.getQueryParameter(URI_PARAM_IS_EXTERNAL_ADD); - if (externalAdd != null && "true".equals(externalAdd)) { + final boolean isExternalAll = externalAdd != null && "true".equals(externalAdd); + if (isExternalAll) { if (!mOpenHelper.initializeExternalAdd(initialValues)) { return null; } @@ -156,7 +164,14 @@ public class LauncherProvider extends ContentProvider { if (rowId < 0) return null; uri = ContentUris.withAppendedId(uri, rowId); - sendNotify(uri); + notifyListeners(); + + if (isExternalAll) { + LauncherAppState app = LauncherAppState.getInstanceNoCreate(); + if (app != null) { + app.reloadWorkspace(); + } + } return uri; } @@ -181,7 +196,7 @@ public class LauncherProvider extends ContentProvider { db.endTransaction(); } - sendNotify(uri); + notifyListeners(); return values.length; } @@ -205,7 +220,7 @@ public class LauncherProvider extends ContentProvider { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count = db.delete(args.table, args.where, args.args); - if (count > 0) sendNotify(uri); + if (count > 0) notifyListeners(); return count; } @@ -217,17 +232,12 @@ public class LauncherProvider extends ContentProvider { addModifiedTime(values); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count = db.update(args.table, values, args.where, args.args); - if (count > 0) sendNotify(uri); + if (count > 0) notifyListeners(); return count; } - private void sendNotify(Uri uri) { - String notify = uri.getQueryParameter(PARAMETER_NOTIFY); - if (notify == null || "true".equals(notify)) { - getContext().getContentResolver().notifyChange(uri, null); - } - + private void notifyListeners() { // always notify the backup agent LauncherBackupAgentHelper.dataChanged(getContext()); if (mListener != null) { @@ -235,7 +245,7 @@ public class LauncherProvider extends ContentProvider { } } - private static void addModifiedTime(ContentValues values) { + @Thunk static void addModifiedTime(ContentValues values) { values.put(LauncherSettings.ChangeLogColumns.MODIFIED, System.currentTimeMillis()); } @@ -251,12 +261,6 @@ public class LauncherProvider extends ContentProvider { return mOpenHelper.generateNewScreenId(); } - // This is only required one time while loading the workspace during the - // upgrade path, and should never be called from anywhere else. - public void updateMaxScreenId(long maxScreenId) { - mOpenHelper.updateMaxScreenId(maxScreenId); - } - /** * Clears all the data for a fresh start. */ @@ -274,9 +278,10 @@ public class LauncherProvider extends ContentProvider { /** * Loads the default workspace based on the following priority scheme: - * 1) From a package provided by play store - * 2) From a partner configuration APK, already in the system image - * 3) The default configuration for the particular device + * 1) From the app restrictions + * 2) From a package provided by play store + * 3) From a partner configuration APK, already in the system image + * 4) The default configuration for the particular device */ synchronized public void loadDefaultFavoritesIfNecessary() { String spKey = LauncherAppState.getSharedPreferencesKey(); @@ -285,9 +290,11 @@ public class LauncherProvider extends ContentProvider { if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) { Log.d(TAG, "loading default workspace"); - AutoInstallsLayout loader = AutoInstallsLayout.get(getContext(), - mOpenHelper.mAppWidgetHost, mOpenHelper); - + AutoInstallsLayout loader = createWorkspaceLoaderFromAppRestriction(); + if (loader == null) { + loader = AutoInstallsLayout.get(getContext(), + mOpenHelper.mAppWidgetHost, mOpenHelper); + } if (loader == null) { final Partner partner = Partner.get(getContext().getPackageManager()); if (partner != null && partner.hasDefaultLayout()) { @@ -321,9 +328,43 @@ public class LauncherProvider extends ContentProvider { } } + /** + * Creates workspace loader from an XML resource listed in the app restrictions. + * + * @return the loader if the restrictions are set and the resource exists; null otherwise. + */ + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) + private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction() { + // UserManager.getApplicationRestrictions() requires minSdkVersion >= 18 + if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + return null; + } + + Context ctx = getContext(); + UserManager um = (UserManager) ctx.getSystemService(Context.USER_SERVICE); + Bundle bundle = um.getApplicationRestrictions(ctx.getPackageName()); + if (bundle == null) { + return null; + } + + String packageName = bundle.getString(RESTRICTION_PACKAGE_NAME); + if (packageName != null) { + try { + Resources targetResources = ctx.getPackageManager() + .getResourcesForApplication(packageName); + return AutoInstallsLayout.get(ctx, packageName, targetResources, + mOpenHelper.mAppWidgetHost, mOpenHelper); + } catch (NameNotFoundException e) { + Log.e(TAG, "Target package for restricted profile not found", e); + return null; + } + } + return null; + } + private DefaultLayoutParser getDefaultLayoutParser() { int defaultLayout = LauncherAppState.getInstance() - .getDynamicGrid().getDeviceProfile().defaultLayoutId; + .getInvariantDeviceProfile().defaultLayoutId; return new DefaultLayoutParser(getContext(), mOpenHelper.mAppWidgetHost, mOpenHelper, getContext().getResources(), defaultLayout); } @@ -337,6 +378,11 @@ public class LauncherProvider extends ContentProvider { mOpenHelper.updateFolderItemsRank(mOpenHelper.getWritableDatabase(), false); } + public void convertShortcutsToLauncherActivities() { + mOpenHelper.convertShortcutsToLauncherActivities(mOpenHelper.getWritableDatabase()); + } + + public void deleteDatabase() { // Are you sure? (y/n) final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); @@ -350,7 +396,7 @@ public class LauncherProvider extends ContentProvider { private static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback { private final Context mContext; - private final AppWidgetHost mAppWidgetHost; + @Thunk final AppWidgetHost mAppWidgetHost; private long mMaxItemId = -1; private long mMaxScreenId = -1; @@ -421,7 +467,8 @@ public class LauncherProvider extends ContentProvider { "modified INTEGER NOT NULL DEFAULT 0," + "restored INTEGER NOT NULL DEFAULT 0," + "profileId INTEGER DEFAULT " + userSerialNumber + "," + - "rank INTEGER NOT NULL DEFAULT 0" + + "rank INTEGER NOT NULL DEFAULT 0," + + "options INTEGER NOT NULL DEFAULT 0" + ");"); addWorkspacesTable(db); @@ -434,6 +481,9 @@ public class LauncherProvider extends ContentProvider { // Fresh and clean launcher DB. mMaxItemId = initializeMaxItemId(db); setFlagEmptyDbCreated(); + + // When a new DB is created, remove all previously stored managed profile information. + ManagedProfileHeuristic.processAllUsers(Collections.EMPTY_LIST, mContext); } private void addWorkspacesTable(SQLiteDatabase db) { @@ -478,142 +528,120 @@ public class LauncherProvider extends ContentProvider { private void setFlagJustLoadedOldDb() { String spKey = LauncherAppState.getSharedPreferencesKey(); SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE); - SharedPreferences.Editor editor = sp.edit(); - editor.putBoolean(UPGRADED_FROM_OLD_DATABASE, true); - editor.putBoolean(EMPTY_DATABASE_CREATED, false); - editor.commit(); + sp.edit().putBoolean(EMPTY_DATABASE_CREATED, false).commit(); } private void setFlagEmptyDbCreated() { String spKey = LauncherAppState.getSharedPreferencesKey(); SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE); - SharedPreferences.Editor editor = sp.edit(); - editor.putBoolean(EMPTY_DATABASE_CREATED, true); - editor.putBoolean(UPGRADED_FROM_OLD_DATABASE, false); - editor.commit(); + sp.edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (LOGD) Log.d(TAG, "onUpgrade triggered: " + oldVersion); - - int version = oldVersion; - if (version < MIN_DATABASE_VERSION) { - // The version cannot be lower that this, as Launcher3 never supported a lower + switch (oldVersion) { + // The version cannot be lower that 12, as Launcher3 never supported a lower // version of the DB. - createEmptyDB(db); - version = DATABASE_VERSION; - } - - if (version < 13) { - // With the new shrink-wrapped and re-orderable workspaces, it makes sense - // to persist workspace screens and their relative order. - mMaxScreenId = 0; - - addWorkspacesTable(db); - version = 13; - } - - if (version < 14) { - db.beginTransaction(); - try { - // Insert new column for holding widget provider name - db.execSQL("ALTER TABLE favorites " + - "ADD COLUMN appWidgetProvider TEXT;"); - db.setTransactionSuccessful(); - version = 14; - } catch (SQLException ex) { - // Old version remains, which means we wipe old data - Log.e(TAG, ex.getMessage(), ex); - } finally { - db.endTransaction(); + case 12: { + // With the new shrink-wrapped and re-orderable workspaces, it makes sense + // to persist workspace screens and their relative order. + mMaxScreenId = 0; + addWorkspacesTable(db); } - } - - if (version < 15) { - db.beginTransaction(); - try { - // 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(); - version = 15; - } catch (SQLException ex) { - // Old version remains, which means we wipe old data - Log.e(TAG, ex.getMessage(), ex); - } finally { - db.endTransaction(); + case 13: { + db.beginTransaction(); + try { + // Insert new column for holding widget provider name + db.execSQL("ALTER TABLE favorites " + + "ADD COLUMN appWidgetProvider TEXT;"); + db.setTransactionSuccessful(); + } catch (SQLException ex) { + Log.e(TAG, ex.getMessage(), ex); + // Old version remains, which means we wipe old data + break; + } finally { + db.endTransaction(); + } } - } - - - if (version < 16) { - db.beginTransaction(); - try { - // Insert new column for holding restore status - db.execSQL("ALTER TABLE favorites " + - "ADD COLUMN restored INTEGER NOT NULL DEFAULT 0;"); - db.setTransactionSuccessful(); - version = 16; - } catch (SQLException ex) { - // Old version remains, which means we wipe old data - Log.e(TAG, ex.getMessage(), ex); - } finally { - db.endTransaction(); + case 14: { + db.beginTransaction(); + try { + // 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(); + } catch (SQLException ex) { + Log.e(TAG, ex.getMessage(), ex); + // Old version remains, which means we wipe old data + break; + } finally { + db.endTransaction(); + } } - } - - if (version < 17) { - // We use the db version upgrade here to identify users who may not have seen - // clings yet (because they weren't available), but for whom the clings are now - // available (tablet users). Because one of the possible cling flows (migration) - // is very destructive (wipes out workspaces), we want to prevent this from showing - // until clear data. We do so by marking that the clings have been shown. - LauncherClings.synchonouslyMarkFirstRunClingDismissed(mContext); - version = 17; - } - - if (version < 18) { - // No-op - version = 18; - } - - if (version < 19) { - // Due to a data loss bug, some users may have items associated with screen ids - // which no longer exist. Since this can cause other problems, and since the user - // will never see these items anyway, we use database upgrade as an opportunity to - // clean things up. - removeOrphanedItems(db); - version = 19; - } - - if (version < 20) { - // Add userId column - if (addProfileColumn(db)) { - version = 20; + case 15: { + if (!addIntegerColumn(db, Favorites.RESTORED, 0)) { + // Old version remains, which means we wipe old data + break; + } } - // else old version remains, which means we wipe old data - } - - if (version < 21) { - if (updateFolderItemsRank(db, true)) { - version = 21; + case 16: { + // We use the db version upgrade here to identify users who may not have seen + // clings yet (because they weren't available), but for whom the clings are now + // available (tablet users). Because one of the possible cling flows (migration) + // is very destructive (wipes out workspaces), we want to prevent this from showing + // until clear data. We do so by marking that the clings have been shown. + LauncherClings.synchonouslyMarkFirstRunClingDismissed(mContext); } - } - - if (version == 21) { - // Recreate workspace table with screen id a primary key - if (recreateWorkspaceTable(db)) { - version = 22; + case 17: { + // No-op + } + case 18: { + // Due to a data loss bug, some users may have items associated with screen ids + // which no longer exist. Since this can cause other problems, and since the user + // will never see these items anyway, we use database upgrade as an opportunity to + // clean things up. + removeOrphanedItems(db); + } + case 19: { + // Add userId column + if (!addProfileColumn(db)) { + // Old version remains, which means we wipe old data + break; + } + } + case 20: + if (!updateFolderItemsRank(db, true)) { + break; + } + case 21: + // Recreate workspace table with screen id a primary key + if (!recreateWorkspaceTable(db)) { + break; + } + case 22: { + if (!addIntegerColumn(db, Favorites.OPTIONS, 0)) { + // Old version remains, which means we wipe old data + break; + } + } + case 23: + // No-op + case 24: + ManagedProfileHeuristic.markExistingUsersForNoFolderCreation(mContext); + case 25: + convertShortcutsToLauncherActivities(db); + case 26: { + // DB Upgraded successfully + return; } } - if (version != DATABASE_VERSION) { - Log.w(TAG, "Destroying all old data."); - createEmptyDB(db); - } + // DB was not upgraded + Log.w(TAG, "Destroying all old data."); + createEmptyDB(db); } @Override @@ -624,7 +652,6 @@ public class LauncherProvider extends ContentProvider { createEmptyDB(db); } - /** * Clears all the data for a fresh start. */ @@ -635,6 +662,63 @@ public class LauncherProvider extends ContentProvider { } /** + * Replaces all shortcuts of type {@link Favorites#ITEM_TYPE_SHORTCUT} which have a valid + * 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 = UserManagerCompat.getInstance(mContext) + .getSerialNumberForUser(UserHandleCompat.myUserHandle()); + c = db.query(TABLE_FAVORITES, 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=?"); + + final int idIndex = c.getColumnIndexOrThrow(Favorites._ID); + final int intentIndex = c.getColumnIndexOrThrow(Favorites.INTENT); + + while (c.moveToNext()) { + String intentDescription = c.getString(intentIndex); + Intent intent; + try { + intent = Intent.parseUri(intentDescription, 0); + } catch (URISyntaxException e) { + Log.e(TAG, "Unable to parse intent", e); + continue; + } + + if (!InstallShortcutReceiver.isLauncherActivity(intent, mContext)) { + continue; + } + + long id = c.getLong(idIndex); + updateStmt.bindLong(1, id); + updateStmt.execute(); + } + db.setTransactionSuccessful(); + } catch (SQLException ex) { + Log.w(TAG, "Error deduping shortcuts", ex); + } finally { + db.endTransaction(); + if (c != null) { + c.close(); + } + if (updateStmt != null) { + updateStmt.close(); + } + } + } + + /** * Recreates workspace table and migrates data to the new table. */ public boolean recreateWorkspaceTable(SQLiteDatabase db) { @@ -682,7 +766,7 @@ public class LauncherProvider extends ContentProvider { return true; } - private boolean updateFolderItemsRank(SQLiteDatabase db, boolean addRankColumn) { + @Thunk boolean updateFolderItemsRank(SQLiteDatabase db, boolean addRankColumn) { db.beginTransaction(); try { if (addRankColumn) { @@ -715,20 +799,21 @@ public class LauncherProvider extends ContentProvider { } private boolean addProfileColumn(SQLiteDatabase db) { + UserManagerCompat userManager = UserManagerCompat.getInstance(mContext); + // Default to the serial number of this user, for older + // shortcuts. + long userSerialNumber = userManager.getSerialNumberForUser( + UserHandleCompat.myUserHandle()); + return addIntegerColumn(db, Favorites.PROFILE_ID, userSerialNumber); + } + + private boolean addIntegerColumn(SQLiteDatabase db, String columnName, long defaultValue) { db.beginTransaction(); try { - UserManagerCompat userManager = UserManagerCompat.getInstance(mContext); - // Default to the serial number of this user, for older - // shortcuts. - long userSerialNumber = userManager.getSerialNumberForUser( - UserHandleCompat.myUserHandle()); - // Insert new column for holding user serial number - db.execSQL("ALTER TABLE favorites " + - "ADD COLUMN profileId INTEGER DEFAULT " - + userSerialNumber + ";"); + db.execSQL("ALTER TABLE favorites ADD COLUMN " + + columnName + " INTEGER NOT NULL DEFAULT " + defaultValue + ";"); db.setTransactionSuccessful(); } catch (SQLException ex) { - // Old version remains, which means we wipe old data Log.e(TAG, ex.getMessage(), ex); return false; } finally { @@ -770,23 +855,7 @@ public class LauncherProvider extends ContentProvider { } private long initializeMaxItemId(SQLiteDatabase db) { - Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null); - - // get the result - final int maxIdIndex = 0; - long id = -1; - if (c != null && c.moveToNext()) { - id = c.getLong(maxIdIndex); - } - if (c != null) { - c.close(); - } - - if (id == -1) { - throw new RuntimeException("Error: could not query max item id"); - } - - return id; + return getMaxId(db, TABLE_FAVORITES); } // Generates a new ID to use for an workspace screen in your database. This method @@ -799,40 +868,14 @@ public class LauncherProvider extends ContentProvider { throw new RuntimeException("Error: max screen id was not initialized"); } mMaxScreenId += 1; - // Log to disk - Launcher.addDumpLog(TAG, "11683562 - generateNewScreenId(): " + mMaxScreenId, true); return mMaxScreenId; } - public void updateMaxScreenId(long maxScreenId) { - // Log to disk - Launcher.addDumpLog(TAG, "11683562 - updateMaxScreenId(): " + maxScreenId, true); - mMaxScreenId = maxScreenId; - } - private long initializeMaxScreenId(SQLiteDatabase db) { - Cursor c = db.rawQuery("SELECT MAX(" + LauncherSettings.WorkspaceScreens._ID + ") FROM " + TABLE_WORKSPACE_SCREENS, null); - - // get the result - final int maxIdIndex = 0; - long id = -1; - if (c != null && c.moveToNext()) { - id = c.getLong(maxIdIndex); - } - if (c != null) { - c.close(); - } - - if (id == -1) { - throw new RuntimeException("Error: could not query max screen id"); - } - - // Log to disk - Launcher.addDumpLog(TAG, "11683562 - initializeMaxScreenId(): " + id, true); - return id; + return getMaxId(db, TABLE_WORKSPACE_SCREENS); } - private boolean initializeExternalAdd(ContentValues values) { + @Thunk boolean initializeExternalAdd(ContentValues values) { // 1. Ensure that externally added items have a valid item id long id = generateNewItemId(); values.put(LauncherSettings.Favorites._ID, id); @@ -919,7 +962,7 @@ public class LauncherProvider extends ContentProvider { return rank; } - private int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) { + @Thunk int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) { ArrayList<Long> screenIds = new ArrayList<Long>(); // TODO: Use multiple loaders with fall-back and transaction. int count = loader.loadLayout(db, screenIds); @@ -946,7 +989,7 @@ public class LauncherProvider extends ContentProvider { return count; } - private void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) { + @Thunk void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) { final ContentResolver resolver = mContext.getContentResolver(); Cursor c = null; int count = 0; @@ -997,10 +1040,10 @@ public class LauncherProvider extends ContentProvider { int curY = 0; final LauncherAppState app = LauncherAppState.getInstance(); - final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - final int width = (int) grid.numColumns; - final int height = (int) grid.numRows; - final int hotseatWidth = (int) grid.numHotseatIcons; + final InvariantDeviceProfile profile = app.getInvariantDeviceProfile(); + final int width = (int) profile.numColumns; + final int height = (int) profile.numRows; + final int hotseatWidth = (int) profile.numHotseatIcons; final HashSet<String> seenIntents = new HashSet<String>(c.getCount()); @@ -1142,7 +1185,7 @@ public class LauncherProvider extends ContentProvider { int hotseatX = hotseat.keyAt(idx); ContentValues values = hotseat.valueAt(idx); - if (hotseatX == grid.hotseatAllAppsRank) { + if (hotseatX == profile.hotseatAllAppsRank) { // let's drop this in the next available hole in the hotseat while (++hotseatX < hotseatWidth) { if (hotseat.get(hotseatX) == null) { @@ -1242,6 +1285,27 @@ public class LauncherProvider extends ContentProvider { } } + /** + * @return the max _id in the provided table. + */ + @Thunk static long getMaxId(SQLiteDatabase db, String table) { + Cursor c = db.rawQuery("SELECT MAX(_id) FROM " + table, null); + // get the result + long id = -1; + if (c != null && c.moveToNext()) { + id = c.getLong(0); + } + if (c != null) { + c.close(); + } + + if (id == -1) { + throw new RuntimeException("Error: could not query max id in " + table); + } + + return id; + } + static class SqlArguments { public final String table; public final String where; |