diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java index e54337050d..f041ffbe6c 100644 --- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java +++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java @@ -16,6 +16,7 @@ import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; import com.android.launcher3.LauncherSettings.Favorites; +import com.android.launcher3.model.DatabaseHelper; import com.android.launcher3.model.LoaderTask; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.model.data.LauncherAppWidgetInfo; @@ -51,8 +52,8 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { * Updates the app widgets whose id has changed during the restore process. */ @WorkerThread - public static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds, - @NonNull AppWidgetHost host) { + public static void restoreAppWidgetIds(Context context, DatabaseHelper helper, + int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) { if (WidgetsModel.GO_DISABLE_WIDGETS) { Log.e(TAG, "Skipping widget ID remap as widgets not supported"); host.deleteHost(); @@ -90,14 +91,16 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { String oldWidgetId = Integer.toString(oldWidgetIds[i]); final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?"; final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) }; - int result = new ContentWriter(context, new ContentWriter.CommitParams(where, args)) + int result = new ContentWriter(context, + new ContentWriter.CommitParams(helper, where, args)) .put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]) .put(LauncherSettings.Favorites.RESTORED, state) .commit(); if (result == 0) { - Cursor cursor = cr.query(Favorites.CONTENT_URI, + Cursor cursor = helper.getWritableDatabase().query( + Favorites.TABLE_NAME, new String[] {Favorites.APPWIDGET_ID}, - "appWidgetId=?", new String[] { oldWidgetId }, null); + "appWidgetId=?", new String[] { oldWidgetId }, null, null, null); try { if (!cursor.moveToFirst()) { // The widget no long exists. diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 06ac44a744..0e027f8478 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -50,6 +50,7 @@ import com.android.launcher3.model.CacheDataUpdatedTask; import com.android.launcher3.model.ItemInstallQueue; import com.android.launcher3.model.LauncherBinder; import com.android.launcher3.model.LoaderTask; +import com.android.launcher3.model.ModelDbController; import com.android.launcher3.model.ModelDelegate; import com.android.launcher3.model.ModelWriter; import com.android.launcher3.model.PackageIncrementalDownloadUpdatedTask; @@ -94,6 +95,8 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi @NonNull private final LauncherAppState mApp; @NonNull + private final ModelDbController mModelDbController; + @NonNull private final Object mLock = new Object(); @Nullable private LoaderTask mLoaderTask; @@ -143,6 +146,7 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi @NonNull final IconCache iconCache, @NonNull final AppFilter appFilter, final boolean isPrimaryInstance) { mApp = app; + mModelDbController = new ModelDbController(context); mBgAllAppsList = new AllAppsList(iconCache, appFilter); mModelDelegate = ModelDelegate.newInstance(context, app, mBgAllAppsList, mBgDataModel, isPrimaryInstance); @@ -153,6 +157,10 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi return mModelDelegate; } + public ModelDbController getModelDbController() { + return mModelDbController; + } + /** * Adds the provided items to the workspace. */ diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index d30d23ceda..0df4bd409e 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -50,8 +50,6 @@ public class LauncherProvider extends ContentProvider { public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings"; - protected ModelDbController mModelDbController; - /** * $ adb shell dumpsys activity provider com.android.launcher3 */ @@ -69,7 +67,6 @@ public class LauncherProvider extends ContentProvider { if (FeatureFlags.IS_STUDIO_BUILD) { Log.d(TAG, "Launcher process started"); } - mModelDbController = new ModelDbController(getContext()); // The content provider exists for the entire duration of the launcher main process and // is the first component to get created. @@ -77,6 +74,10 @@ public class LauncherProvider extends ContentProvider { return true; } + public ModelDbController getModelDbController() { + return LauncherAppState.getInstance(getContext()).getModel().getModelDbController(); + } + @Override public String getType(Uri uri) { SqlArguments args = new SqlArguments(uri, null, null); @@ -95,7 +96,7 @@ public class LauncherProvider extends ContentProvider { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(args.table); - Cursor result = mModelDbController.query( + Cursor result = getModelDbController().query( args.table, projection, args.where, args.args, sortOrder); result.setNotificationUri(getContext().getContentResolver(), uri); return result; @@ -120,7 +121,7 @@ public class LauncherProvider extends ContentProvider { } SqlArguments args = new SqlArguments(uri); - int rowId = mModelDbController.insert(args.table, initialValues); + int rowId = getModelDbController().insert(args.table, initialValues); if (rowId < 0) return null; uri = ContentUris.withAppendedId(uri, rowId); @@ -130,7 +131,7 @@ public class LauncherProvider extends ContentProvider { private boolean initializeExternalAdd(ContentValues values) { // 1. Ensure that externally added items have a valid item id - int id = mModelDbController.generateNewItemId(); + int id = getModelDbController().generateNewItemId(); values.put(LauncherSettings.Favorites._ID, id); // 2. In the case of an app widget, and if no app widget id is specified, we @@ -171,7 +172,7 @@ public class LauncherProvider extends ContentProvider { @Override public int bulkInsert(Uri uri, ContentValues[] values) { SqlArguments args = new SqlArguments(uri); - mModelDbController.bulkInsert(args.table, values); + getModelDbController().bulkInsert(args.table, values); reloadLauncherIfExternal(); return values.length; } @@ -180,7 +181,7 @@ public class LauncherProvider extends ContentProvider { @Override public ContentProviderResult[] applyBatch(ArrayList operations) throws OperationApplicationException { - try (SQLiteTransaction t = mModelDbController.newTransaction()) { + try (SQLiteTransaction t = getModelDbController().newTransaction()) { final int numOperations = operations.size(); final ContentProviderResult[] results = new ContentProviderResult[numOperations]; for (int i = 0; i < numOperations; i++) { @@ -196,7 +197,7 @@ public class LauncherProvider extends ContentProvider { @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SqlArguments args = new SqlArguments(uri, selection, selectionArgs); - int count = mModelDbController.delete(args.table, args.where, args.args); + int count = getModelDbController().delete(args.table, args.where, args.args); if (count > 0) { reloadLauncherIfExternal(); } @@ -206,7 +207,7 @@ public class LauncherProvider extends ContentProvider { @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SqlArguments args = new SqlArguments(uri, selection, selectionArgs); - int count = mModelDbController.update(args.table, values, args.where, args.args); + int count = getModelDbController().update(args.table, values, args.where, args.args); reloadLauncherIfExternal(); return count; } @@ -219,59 +220,59 @@ public class LauncherProvider extends ContentProvider { switch (method) { case LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG: { - mModelDbController.clearEmptyDbFlag(); + getModelDbController().clearEmptyDbFlag(); return null; } case LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS: { Bundle result = new Bundle(); result.putIntArray(LauncherSettings.Settings.EXTRA_VALUE, - mModelDbController.deleteEmptyFolders().toArray()); + getModelDbController().deleteEmptyFolders().toArray()); return result; } case LauncherSettings.Settings.METHOD_NEW_ITEM_ID: { Bundle result = new Bundle(); result.putInt(LauncherSettings.Settings.EXTRA_VALUE, - mModelDbController.generateNewItemId()); + getModelDbController().generateNewItemId()); return result; } case LauncherSettings.Settings.METHOD_NEW_SCREEN_ID: { Bundle result = new Bundle(); result.putInt(LauncherSettings.Settings.EXTRA_VALUE, - mModelDbController.getNewScreenId()); + getModelDbController().getNewScreenId()); return result; } case LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB: { - mModelDbController.createEmptyDB(); + getModelDbController().createEmptyDB(); return null; } case LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES: { - mModelDbController.loadDefaultFavoritesIfNecessary(); + getModelDbController().loadDefaultFavoritesIfNecessary(); return null; } case LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS: { - mModelDbController.removeGhostWidgets(); + getModelDbController().removeGhostWidgets(); return null; } case LauncherSettings.Settings.METHOD_NEW_TRANSACTION: { Bundle result = new Bundle(); result.putBinder(LauncherSettings.Settings.EXTRA_VALUE, - mModelDbController.newTransaction()); + getModelDbController().newTransaction()); return result; } case LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE: { - mModelDbController.refreshHotseatRestoreTable(); + getModelDbController().refreshHotseatRestoreTable(); return null; } case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: { Bundle result = new Bundle(); result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, - mModelDbController.updateCurrentOpenHelper(arg /* dbFile */)); + getModelDbController().updateCurrentOpenHelper(arg /* dbFile */)); return result; } case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: { Bundle result = new Bundle(); result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, - mModelDbController.prepareForPreview(arg /* dbFile */)); + getModelDbController().prepareForPreview(arg /* dbFile */)); return result; } } diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java index c237f5b80b..a5dccc1fab 100644 --- a/src/com/android/launcher3/model/LoaderCursor.java +++ b/src/com/android/launcher3/model/LoaderCursor.java @@ -65,6 +65,7 @@ public class LoaderCursor extends CursorWrapper { private final LongSparseArray allUsers; + private final LauncherAppState mApp; private final Uri mContentUri; private final Context mContext; private final PackageManager mPM; @@ -111,6 +112,7 @@ public class LoaderCursor extends CursorWrapper { UserManagerState userManagerState) { super(cursor); + mApp = app; allUsers = userManagerState.allUsers; mContentUri = contentUri; mContext = app.getContext(); @@ -388,6 +390,7 @@ public class LoaderCursor extends CursorWrapper { */ public ContentWriter updater() { return new ContentWriter(mContext, new ContentWriter.CommitParams( + mApp.getModel().getModelDbController().getDatabaseHelper(), BaseColumns._ID + "= ?", new String[]{Integer.toString(id)})); } diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java index 9b54ce131d..97bce8c25a 100644 --- a/src/com/android/launcher3/model/ModelDbController.java +++ b/src/com/android/launcher3/model/ModelDbController.java @@ -50,6 +50,8 @@ import android.util.Base64; import android.util.Log; import android.util.Xml; +import androidx.annotation.WorkerThread; + import com.android.launcher3.AutoInstallsLayout; import com.android.launcher3.AutoInstallsLayout.SourceResources; import com.android.launcher3.DefaultLayoutParser; @@ -115,6 +117,7 @@ public class ModelDbController { /** * Refer {@link SQLiteDatabase#query} */ + @WorkerThread public Cursor query(String table, String[] projection, String selection, String[] selectionArgs, String sortOrder) { createDbIfNotExists(); @@ -131,6 +134,7 @@ public class ModelDbController { /** * Refer {@link SQLiteDatabase#insert(String, String, ContentValues)} */ + @WorkerThread public int insert(String table, ContentValues initialValues) { createDbIfNotExists(); @@ -146,6 +150,7 @@ public class ModelDbController { /** * Similar to insert but for adding multiple values in a transaction. */ + @WorkerThread public int bulkInsert(String table, ContentValues[] values) { createDbIfNotExists(); @@ -167,6 +172,7 @@ public class ModelDbController { /** * Refer {@link SQLiteDatabase#delete(String, String, String[])} */ + @WorkerThread public int delete(String table, String selection, String[] selectionArgs) { createDbIfNotExists(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); @@ -185,6 +191,7 @@ public class ModelDbController { /** * Refer {@link SQLiteDatabase#update(String, ContentValues, String, String[])} */ + @WorkerThread public int update(String table, ContentValues values, String selection, String[] selectionArgs) { createDbIfNotExists(); @@ -198,6 +205,7 @@ public class ModelDbController { /** * Clears a previously set flag corresponding to empty db creation */ + @WorkerThread public void clearEmptyDbFlag() { createDbIfNotExists(); clearFlagEmptyDbCreated(); @@ -206,6 +214,7 @@ public class ModelDbController { /** * Generates an id to be used for new item in the favorites table */ + @WorkerThread public int generateNewItemId() { createDbIfNotExists(); return mOpenHelper.generateNewItemId(); @@ -214,6 +223,7 @@ public class ModelDbController { /** * Generates an id to be used for new workspace screen */ + @WorkerThread public int getNewScreenId() { createDbIfNotExists(); return mOpenHelper.getNewScreenId(); @@ -222,6 +232,7 @@ public class ModelDbController { /** * Creates an empty DB clearing all existing data */ + @WorkerThread public void createEmptyDB() { createDbIfNotExists(); mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase()); @@ -230,6 +241,7 @@ public class ModelDbController { /** * Removes any widget which are present in the framework, but not in out internal DB */ + @WorkerThread public void removeGhostWidgets() { createDbIfNotExists(); mOpenHelper.removeGhostWidgets(mOpenHelper.getWritableDatabase()); @@ -238,6 +250,7 @@ public class ModelDbController { /** * Returns a new {@link SQLiteTransaction} */ + @WorkerThread public SQLiteTransaction newTransaction() { createDbIfNotExists(); return new SQLiteTransaction(mOpenHelper.getWritableDatabase()); @@ -246,6 +259,7 @@ public class ModelDbController { /** * Refreshes the internal state corresponding to presence of hotseat table */ + @WorkerThread public void refreshHotseatRestoreTable() { createDbIfNotExists(); mOpenHelper.mHotseatRestoreTableExists = tableExists( @@ -256,6 +270,7 @@ public class ModelDbController { * Updates the current DB and copies all the existing data to the temp table * @param dbFile name of the target db file name */ + @WorkerThread public boolean updateCurrentOpenHelper(String dbFile) { createDbIfNotExists(); return prepForMigration( @@ -270,6 +285,7 @@ public class ModelDbController { * Returns the current DatabaseHelper. * Only for tests */ + @WorkerThread public DatabaseHelper getDatabaseHelper() { createDbIfNotExists(); return mOpenHelper; @@ -278,6 +294,7 @@ public class ModelDbController { /** * Prepares the DB for preview by copying all existing data to preview table */ + @WorkerThread public boolean prepareForPreview(String dbFile) { createDbIfNotExists(); return prepForMigration( @@ -296,6 +313,7 @@ public class ModelDbController { * Deletes any empty folder from the DB. * @return Ids of deleted folders. */ + @WorkerThread public IntArray deleteEmptyFolders() { createDbIfNotExists(); @@ -338,6 +356,7 @@ public class ModelDbController { * 3) From a partner configuration APK, already in the system image * 4) The default configuration for the particular device */ + @WorkerThread public synchronized void loadDefaultFavoritesIfNecessary() { createDbIfNotExists(); SharedPreferences sp = LauncherPrefs.getPrefs(mContext); diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java index 772ffa4271..ddb8b05839 100644 --- a/src/com/android/launcher3/model/ModelWriter.java +++ b/src/com/android/launcher3/model/ModelWriter.java @@ -33,7 +33,6 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherModel.CallbackTask; import com.android.launcher3.LauncherProvider; -import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.LauncherSettings.Settings; import com.android.launcher3.Utilities; @@ -267,8 +266,7 @@ public class ModelWriter { item.onAddToDatabase(writer); writer.put(Favorites._ID, item.id); - cr.insert(Favorites.CONTENT_URI, writer.getValues(mContext)); - + mModel.getModelDbController().insert(Favorites.TABLE_NAME, writer.getValues(mContext)); synchronized (mBgDataModel) { checkItemInfoLocked(item.id, item, stackTrace); mBgDataModel.addItem(mContext, item, true); @@ -324,13 +322,13 @@ public class ModelWriter { notifyDelete(Collections.singleton(info)); enqueueDeleteRunnable(() -> { - ContentResolver cr = mContext.getContentResolver(); - cr.delete(LauncherSettings.Favorites.CONTENT_URI, - LauncherSettings.Favorites.CONTAINER + "=" + info.id, null); + mModel.getModelDbController().delete(Favorites.TABLE_NAME, + Favorites.CONTAINER + "=" + info.id, null); mBgDataModel.removeItem(mContext, info.contents); info.contents.clear(); - cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null); + mModel.getModelDbController().delete(Favorites.TABLE_NAME, + Favorites._ID + "=" + info.id, null); mBgDataModel.removeItem(mContext, info); verifier.verifyModel(); }); diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index ba5249c144..ac7216449b 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -107,7 +107,7 @@ public class RestoreDbTask { try (SQLiteTransaction t = new SQLiteTransaction(db)) { RestoreDbTask task = new RestoreDbTask(); task.sanitizeDB(context, helper, db, new BackupManager(context)); - task.restoreAppWidgetIdsIfExists(context); + task.restoreAppWidgetIdsIfExists(context, helper); t.commit(); return true; } catch (Exception e) { @@ -321,11 +321,11 @@ public class RestoreDbTask { .putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType())); } - private void restoreAppWidgetIdsIfExists(Context context) { + private void restoreAppWidgetIdsIfExists(Context context, DatabaseHelper helper) { LauncherPrefs lp = LauncherPrefs.get(context); if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) { AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID); - AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, + AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, helper, IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(), IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(), host); diff --git a/src/com/android/launcher3/util/ContentWriter.java b/src/com/android/launcher3/util/ContentWriter.java index 55c2585f4a..e509235688 100644 --- a/src/com/android/launcher3/util/ContentWriter.java +++ b/src/com/android/launcher3/util/ContentWriter.java @@ -19,13 +19,14 @@ package com.android.launcher3.util; import android.content.ContentValues; import android.content.Context; import android.content.Intent; -import android.net.Uri; import android.os.UserHandle; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; +import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.GraphicsUtils; +import com.android.launcher3.model.DatabaseHelper; import com.android.launcher3.pm.UserCache; /** @@ -105,7 +106,8 @@ public class ContentWriter { public int commit() { if (mCommitParams != null) { - return mContext.getContentResolver().update(mCommitParams.mUri, getValues(mContext), + mCommitParams.mDatabaseHelper.getWritableDatabase().update( + Favorites.TABLE_NAME, getValues(mContext), mCommitParams.mWhere, mCommitParams.mSelectionArgs); } return 0; @@ -113,12 +115,12 @@ public class ContentWriter { public static final class CommitParams { - final Uri mUri; + final DatabaseHelper mDatabaseHelper; final String mWhere; final String[] mSelectionArgs; - public CommitParams(String where, String[] selectionArgs) { - mUri = LauncherSettings.Favorites.CONTENT_URI; + public CommitParams(DatabaseHelper helper, String where, String[] selectionArgs) { + mDatabaseHelper = helper; mWhere = where; mSelectionArgs = selectionArgs; } diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java index 9e88c06a9c..bf31e39ccc 100644 --- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java +++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java @@ -62,7 +62,6 @@ import com.android.launcher3.model.AllAppsList; import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.ItemInstallQueue; -import com.android.launcher3.model.ModelDbController; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.pm.InstallSessionHelper; @@ -423,12 +422,11 @@ public class LauncherModelHelper { @Override public boolean onCreate() { - mModelDbController = new ModelDbController(getContext()); return true; } public SQLiteDatabase getDb() { - return mModelDbController.getDatabaseHelper().getWritableDatabase(); + return getModelDbController().getDatabaseHelper().getWritableDatabase(); } }