Merge "Revert "Changing GridMigrationTask to use ModelDbController directly"" into udc-dev am: 178802d35c
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/23028431 Change-Id: I2d75a1d6898416136c1b3d39488369e59e45bbc9 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -16,8 +16,8 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
import com.android.launcher3.LauncherSettings.Favorites;
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
|
import com.android.launcher3.model.DatabaseHelper;
|
||||||
import com.android.launcher3.model.LoaderTask;
|
import com.android.launcher3.model.LoaderTask;
|
||||||
import com.android.launcher3.model.ModelDbController;
|
|
||||||
import com.android.launcher3.model.WidgetsModel;
|
import com.android.launcher3.model.WidgetsModel;
|
||||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||||
import com.android.launcher3.pm.UserCache;
|
import com.android.launcher3.pm.UserCache;
|
||||||
@@ -52,7 +52,7 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
|
|||||||
* Updates the app widgets whose id has changed during the restore process.
|
* Updates the app widgets whose id has changed during the restore process.
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static void restoreAppWidgetIds(Context context, ModelDbController controller,
|
public static void restoreAppWidgetIds(Context context, DatabaseHelper helper,
|
||||||
int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) {
|
int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) {
|
||||||
if (WidgetsModel.GO_DISABLE_WIDGETS) {
|
if (WidgetsModel.GO_DISABLE_WIDGETS) {
|
||||||
Log.e(TAG, "Skipping widget ID remap as widgets not supported");
|
Log.e(TAG, "Skipping widget ID remap as widgets not supported");
|
||||||
@@ -92,12 +92,12 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
|
|||||||
final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
|
final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
|
||||||
final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) };
|
final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) };
|
||||||
int result = new ContentWriter(context,
|
int result = new ContentWriter(context,
|
||||||
new ContentWriter.CommitParams(controller, where, args))
|
new ContentWriter.CommitParams(helper, where, args))
|
||||||
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
|
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
|
||||||
.put(LauncherSettings.Favorites.RESTORED, state)
|
.put(LauncherSettings.Favorites.RESTORED, state)
|
||||||
.commit();
|
.commit();
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
Cursor cursor = controller.getDb().query(
|
Cursor cursor = helper.getWritableDatabase().query(
|
||||||
Favorites.TABLE_NAME,
|
Favorites.TABLE_NAME,
|
||||||
new String[] {Favorites.APPWIDGET_ID},
|
new String[] {Favorites.APPWIDGET_ID},
|
||||||
"appWidgetId=?", new String[] { oldWidgetId }, null, null, null);
|
"appWidgetId=?", new String[] { oldWidgetId }, null, null, null);
|
||||||
|
|||||||
@@ -263,6 +263,18 @@ public class LauncherProvider extends ContentProvider {
|
|||||||
getModelDbController().refreshHotseatRestoreTable();
|
getModelDbController().refreshHotseatRestoreTable();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: {
|
||||||
|
Bundle result = new Bundle();
|
||||||
|
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
|
||||||
|
getModelDbController().updateCurrentOpenHelper(arg /* dbFile */));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: {
|
||||||
|
Bundle result = new Bundle();
|
||||||
|
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
|
||||||
|
getModelDbController().prepareForPreview(arg /* dbFile */));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,6 +147,11 @@ public class LauncherSettings {
|
|||||||
*/
|
*/
|
||||||
public static final String HYBRID_HOTSEAT_BACKUP_TABLE = "hotseat_restore_backup";
|
public static final String HYBRID_HOTSEAT_BACKUP_TABLE = "hotseat_restore_backup";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary table used specifically for grid migrations during wallpaper preview
|
||||||
|
*/
|
||||||
|
public static final String PREVIEW_TABLE_NAME = "favorites_preview";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporary table used specifically for multi-db grid migrations
|
* Temporary table used specifically for multi-db grid migrations
|
||||||
*/
|
*/
|
||||||
@@ -158,6 +163,18 @@ public class LauncherSettings {
|
|||||||
public static final Uri CONTENT_URI = Uri.parse("content://"
|
public static final Uri CONTENT_URI = Uri.parse("content://"
|
||||||
+ LauncherProvider.AUTHORITY + "/" + TABLE_NAME);
|
+ LauncherProvider.AUTHORITY + "/" + TABLE_NAME);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The content:// style URL for "favorites_preview" table
|
||||||
|
*/
|
||||||
|
public static final Uri PREVIEW_CONTENT_URI = Uri.parse("content://"
|
||||||
|
+ LauncherProvider.AUTHORITY + "/" + PREVIEW_TABLE_NAME);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The content:// style URL for "favorites_tmp" table
|
||||||
|
*/
|
||||||
|
public static final Uri TMP_CONTENT_URI = Uri.parse("content://"
|
||||||
|
+ LauncherProvider.AUTHORITY + "/" + TMP_TABLE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The content:// style URL for a given row, identified by its id.
|
* The content:// style URL for a given row, identified by its id.
|
||||||
*
|
*
|
||||||
@@ -359,6 +376,10 @@ public class LauncherSettings {
|
|||||||
|
|
||||||
public static final String METHOD_REFRESH_HOTSEAT_RESTORE_TABLE = "restore_hotseat_table";
|
public static final String METHOD_REFRESH_HOTSEAT_RESTORE_TABLE = "restore_hotseat_table";
|
||||||
|
|
||||||
|
public static final String METHOD_UPDATE_CURRENT_OPEN_HELPER = "update_current_open_helper";
|
||||||
|
|
||||||
|
public static final String METHOD_PREP_FOR_PREVIEW = "prep_for_preview";
|
||||||
|
|
||||||
public static final String EXTRA_VALUE = "value";
|
public static final String EXTRA_VALUE = "value";
|
||||||
|
|
||||||
public static final String EXTRA_DB_NAME = "db_name";
|
public static final String EXTRA_DB_NAME = "db_name";
|
||||||
@@ -372,8 +393,11 @@ public class LauncherSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Bundle call(ContentResolver cr, String method, String arg) {
|
public static Bundle call(ContentResolver cr, String method, String arg) {
|
||||||
return cr.call(CONTENT_URI, method, arg, null);
|
return call(cr, method, arg, null /* extras */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Bundle call(ContentResolver cr, String method, String arg, Bundle extras) {
|
||||||
|
return cr.call(CONTENT_URI, method, arg, extras);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.launcher3.graphics;
|
package com.android.launcher3.graphics;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
|
|
||||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||||
|
|
||||||
@@ -53,8 +52,6 @@ import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewContext;
|
|||||||
import com.android.launcher3.model.BgDataModel;
|
import com.android.launcher3.model.BgDataModel;
|
||||||
import com.android.launcher3.model.GridSizeMigrationUtil;
|
import com.android.launcher3.model.GridSizeMigrationUtil;
|
||||||
import com.android.launcher3.model.LoaderTask;
|
import com.android.launcher3.model.LoaderTask;
|
||||||
import com.android.launcher3.model.ModelDbController;
|
|
||||||
import com.android.launcher3.provider.LauncherDbUtils;
|
|
||||||
import com.android.launcher3.util.ComponentKey;
|
import com.android.launcher3.util.ComponentKey;
|
||||||
import com.android.launcher3.util.RunnableList;
|
import com.android.launcher3.util.RunnableList;
|
||||||
import com.android.launcher3.util.Themes;
|
import com.android.launcher3.util.Themes;
|
||||||
@@ -148,9 +145,7 @@ public class PreviewSurfaceRenderer {
|
|||||||
final String query = LauncherSettings.Favorites.ITEM_TYPE + " = "
|
final String query = LauncherSettings.Favorites.ITEM_TYPE + " = "
|
||||||
+ LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
|
+ LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
|
||||||
|
|
||||||
ModelDbController mainController =
|
try (Cursor c = context.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
|
||||||
LauncherAppState.getInstance(mContext).getModel().getModelDbController();
|
|
||||||
try (Cursor c = mainController.query(TABLE_NAME,
|
|
||||||
new String[] {
|
new String[] {
|
||||||
LauncherSettings.Favorites.APPWIDGET_ID,
|
LauncherSettings.Favorites.APPWIDGET_ID,
|
||||||
LauncherSettings.Favorites.SPANX,
|
LauncherSettings.Favorites.SPANX,
|
||||||
@@ -195,6 +190,8 @@ public class PreviewSurfaceRenderer {
|
|||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
private void loadModelData() {
|
private void loadModelData() {
|
||||||
|
final boolean migrated = doGridMigrationIfNecessary();
|
||||||
|
|
||||||
final Context inflationContext;
|
final Context inflationContext;
|
||||||
if (mWallpaperColors != null) {
|
if (mWallpaperColors != null) {
|
||||||
// Create a themed context, without affecting the main application context
|
// Create a themed context, without affecting the main application context
|
||||||
@@ -212,20 +209,8 @@ public class PreviewSurfaceRenderer {
|
|||||||
Themes.getActivityThemeRes(mContext));
|
Themes.getActivityThemeRes(mContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GridSizeMigrationUtil.needsToMigrate(inflationContext, mIdp)) {
|
if (migrated) {
|
||||||
// Start the migration
|
|
||||||
PreviewContext previewContext = new PreviewContext(inflationContext, mIdp);
|
PreviewContext previewContext = new PreviewContext(inflationContext, mIdp);
|
||||||
// Copy existing data to preview DB
|
|
||||||
LauncherDbUtils.copyTable(LauncherAppState.getInstance(mContext)
|
|
||||||
.getModel().getModelDbController().getDb(),
|
|
||||||
TABLE_NAME,
|
|
||||||
LauncherAppState.getInstance(previewContext)
|
|
||||||
.getModel().getModelDbController().getDb(),
|
|
||||||
TABLE_NAME,
|
|
||||||
mContext);
|
|
||||||
LauncherAppState.getInstance(previewContext)
|
|
||||||
.getModel().getModelDbController().clearEmptyDbFlag();
|
|
||||||
|
|
||||||
new LoaderTask(
|
new LoaderTask(
|
||||||
LauncherAppState.getInstance(previewContext),
|
LauncherAppState.getInstance(previewContext),
|
||||||
/* bgAllAppsList= */ null,
|
/* bgAllAppsList= */ null,
|
||||||
@@ -244,7 +229,8 @@ public class PreviewSurfaceRenderer {
|
|||||||
query += " or " + LauncherSettings.Favorites.SCREEN + " = "
|
query += " or " + LauncherSettings.Favorites.SCREEN + " = "
|
||||||
+ Workspace.SECOND_SCREEN_ID;
|
+ Workspace.SECOND_SCREEN_ID;
|
||||||
}
|
}
|
||||||
loadWorkspace(new ArrayList<>(), query, null);
|
loadWorkspaceForPreviewSurfaceRenderer(new ArrayList<>(),
|
||||||
|
LauncherSettings.Favorites.PREVIEW_CONTENT_URI, query);
|
||||||
|
|
||||||
final SparseArray<Size> spanInfo =
|
final SparseArray<Size> spanInfo =
|
||||||
getLoadedLauncherWidgetInfo(previewContext.getBaseContext());
|
getLoadedLauncherWidgetInfo(previewContext.getBaseContext());
|
||||||
@@ -267,6 +253,14 @@ public class PreviewSurfaceRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
private boolean doGridMigrationIfNecessary() {
|
||||||
|
if (!GridSizeMigrationUtil.needsToMigrate(mContext, mIdp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, mIdp);
|
||||||
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void renderView(Context inflationContext, BgDataModel dataModel,
|
private void renderView(Context inflationContext, BgDataModel dataModel,
|
||||||
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap,
|
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap,
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.launcher3.model;
|
package com.android.launcher3.model;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb;
|
|
||||||
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
||||||
|
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -36,6 +36,9 @@ import androidx.annotation.NonNull;
|
|||||||
|
|
||||||
import com.android.launcher3.AutoInstallsLayout;
|
import com.android.launcher3.AutoInstallsLayout;
|
||||||
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
|
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
|
||||||
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
|
import com.android.launcher3.LauncherFiles;
|
||||||
|
import com.android.launcher3.LauncherPrefs;
|
||||||
import com.android.launcher3.LauncherSettings;
|
import com.android.launcher3.LauncherSettings;
|
||||||
import com.android.launcher3.LauncherSettings.Favorites;
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
@@ -55,7 +58,6 @@ import java.io.File;
|
|||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.function.ToLongFunction;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,23 +76,45 @@ public class DatabaseHelper extends NoLocaleSQLiteHelper implements
|
|||||||
private static final boolean LOGD = false;
|
private static final boolean LOGD = false;
|
||||||
|
|
||||||
private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
|
private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
|
||||||
|
public static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final ToLongFunction<UserHandle> mUserSerialProvider;
|
private final boolean mForMigration;
|
||||||
private final Runnable mOnEmptyDbCreateCallback;
|
|
||||||
|
|
||||||
private int mMaxItemId = -1;
|
private int mMaxItemId = -1;
|
||||||
public boolean mHotseatRestoreTableExists;
|
public boolean mHotseatRestoreTableExists;
|
||||||
|
|
||||||
|
public static DatabaseHelper createDatabaseHelper(Context context, boolean forMigration) {
|
||||||
|
return createDatabaseHelper(context, null, forMigration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DatabaseHelper createDatabaseHelper(Context context, String dbName,
|
||||||
|
boolean forMigration) {
|
||||||
|
if (dbName == null) {
|
||||||
|
dbName = InvariantDeviceProfile.INSTANCE.get(context).dbFile;
|
||||||
|
}
|
||||||
|
DatabaseHelper databaseHelper = new DatabaseHelper(context, dbName, forMigration);
|
||||||
|
// Table creation sometimes fails silently, which leads to a crash loop.
|
||||||
|
// This way, we will try to create a table every time after crash, so the device
|
||||||
|
// would eventually be able to recover.
|
||||||
|
if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) {
|
||||||
|
Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
|
||||||
|
// This operation is a no-op if the table already exists.
|
||||||
|
databaseHelper.addFavoritesTable(databaseHelper.getWritableDatabase(), true);
|
||||||
|
}
|
||||||
|
databaseHelper.mHotseatRestoreTableExists = tableExists(
|
||||||
|
databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
|
||||||
|
|
||||||
|
databaseHelper.initIds();
|
||||||
|
return databaseHelper;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor used in tests and for restore.
|
* Constructor used in tests and for restore.
|
||||||
*/
|
*/
|
||||||
public DatabaseHelper(Context context, String dbName,
|
public DatabaseHelper(Context context, String dbName, boolean forMigration) {
|
||||||
ToLongFunction<UserHandle> userSerialProvider, Runnable onEmptyDbCreateCallback) {
|
|
||||||
super(context, dbName, SCHEMA_VERSION);
|
super(context, dbName, SCHEMA_VERSION);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mUserSerialProvider = userSerialProvider;
|
mForMigration = forMigration;
|
||||||
mOnEmptyDbCreateCallback = onEmptyDbCreateCallback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initIds() {
|
protected void initIds() {
|
||||||
@@ -107,11 +131,13 @@ public class DatabaseHelper extends NoLocaleSQLiteHelper implements
|
|||||||
|
|
||||||
mMaxItemId = 1;
|
mMaxItemId = 1;
|
||||||
|
|
||||||
addTableToDb(db, getDefaultUserSerial(), false /* optional */);
|
addFavoritesTable(db, false);
|
||||||
|
|
||||||
// Fresh and clean launcher DB.
|
// Fresh and clean launcher DB.
|
||||||
mMaxItemId = initializeMaxItemId(db);
|
mMaxItemId = initializeMaxItemId(db);
|
||||||
mOnEmptyDbCreateCallback.run();
|
if (!mForMigration) {
|
||||||
|
onEmptyDbCreated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAddOrDeleteOp(SQLiteDatabase db) {
|
public void onAddOrDeleteOp(SQLiteDatabase db) {
|
||||||
@@ -121,8 +147,38 @@ public class DatabaseHelper extends NoLocaleSQLiteHelper implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getDefaultUserSerial() {
|
/**
|
||||||
return mUserSerialProvider.applyAsLong(Process.myUserHandle());
|
* Re-composite given key in respect to database. If the current db is
|
||||||
|
* {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
|
||||||
|
* given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
|
||||||
|
* string will be "EMPTY_DATABASE_CREATED@minimal.db".
|
||||||
|
*/
|
||||||
|
public String getKey(final String key) {
|
||||||
|
if (TextUtils.equals(getDatabaseName(), LauncherFiles.LAUNCHER_DB)) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
return key + "@" + getDatabaseName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden in tests.
|
||||||
|
*/
|
||||||
|
protected void onEmptyDbCreated() {
|
||||||
|
// Set the flag for empty DB
|
||||||
|
LauncherPrefs.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSerialNumberForUser(UserHandle user) {
|
||||||
|
return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDefaultUserSerial() {
|
||||||
|
return getSerialNumberForUser(Process.myUserHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFavoritesTable(SQLiteDatabase db, boolean optional) {
|
||||||
|
Favorites.addTableToDb(db, getDefaultUserSerial(), optional);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package com.android.launcher3.model;
|
package com.android.launcher3.model;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
|
|
||||||
import static com.android.launcher3.LauncherSettings.Favorites.TMP_TABLE;
|
|
||||||
import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
|
|
||||||
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -37,15 +34,16 @@ import android.util.Log;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.launcher3.InvariantDeviceProfile;
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
|
import com.android.launcher3.LauncherAppState;
|
||||||
import com.android.launcher3.LauncherSettings;
|
import com.android.launcher3.LauncherSettings;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
|
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||||
import com.android.launcher3.model.data.ItemInfo;
|
import com.android.launcher3.model.data.ItemInfo;
|
||||||
import com.android.launcher3.pm.InstallSessionHelper;
|
import com.android.launcher3.pm.InstallSessionHelper;
|
||||||
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
|
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
|
||||||
import com.android.launcher3.util.GridOccupancy;
|
import com.android.launcher3.util.GridOccupancy;
|
||||||
import com.android.launcher3.util.IntArray;
|
import com.android.launcher3.util.IntArray;
|
||||||
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
|
|
||||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||||
import com.android.launcher3.widget.WidgetManagerHelper;
|
import com.android.launcher3.widget.WidgetManagerHelper;
|
||||||
|
|
||||||
@@ -91,38 +89,81 @@ public class GridSizeMigrationUtil {
|
|||||||
return needsToMigrate;
|
return needsToMigrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** See {@link #migrateGridIfNeeded(Context, InvariantDeviceProfile)} */
|
||||||
|
public static boolean migrateGridIfNeeded(Context context) {
|
||||||
|
if (context instanceof LauncherPreviewRenderer.PreviewContext) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return migrateGridIfNeeded(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When migrating the grid, we copy the table
|
* When migrating the grid for preview, we copy the table
|
||||||
* {@link LauncherSettings.Favorites#TABLE_NAME} from {@code source} into
|
* {@link LauncherSettings.Favorites#TABLE_NAME} into
|
||||||
* {@link LauncherSettings.Favorites#TMP_TABLE}, run the grid size migration algorithm
|
* {@link LauncherSettings.Favorites#PREVIEW_TABLE_NAME}, run grid size migration from the
|
||||||
|
* former to the later, then use the later table for preview.
|
||||||
|
*
|
||||||
|
* Similarly when doing the actual grid migration, the former grid option's table
|
||||||
|
* {@link LauncherSettings.Favorites#TABLE_NAME} is copied into the new grid option's
|
||||||
|
* {@link LauncherSettings.Favorites#TMP_TABLE}, we then run the grid size migration algorithm
|
||||||
* to migrate the later to the former, and load the workspace from the default
|
* to migrate the later to the former, and load the workspace from the default
|
||||||
* {@link LauncherSettings.Favorites#TABLE_NAME}.
|
* {@link LauncherSettings.Favorites#TABLE_NAME}.
|
||||||
*
|
*
|
||||||
* @return false if the migration failed.
|
* @return false if the migration failed.
|
||||||
*/
|
*/
|
||||||
public static boolean migrateGridIfNeeded(
|
public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) {
|
||||||
@NonNull Context context,
|
boolean migrateForPreview = idp != null;
|
||||||
@NonNull InvariantDeviceProfile idp,
|
if (!migrateForPreview) {
|
||||||
@NonNull DatabaseHelper target,
|
idp = LauncherAppState.getIDP(context);
|
||||||
@NonNull SQLiteDatabase source) {
|
}
|
||||||
|
|
||||||
DeviceGridState srcDeviceState = new DeviceGridState(context);
|
DeviceGridState srcDeviceState = new DeviceGridState(context);
|
||||||
DeviceGridState destDeviceState = new DeviceGridState(idp);
|
DeviceGridState destDeviceState = new DeviceGridState(idp);
|
||||||
if (!needsToMigrate(srcDeviceState, destDeviceState)) {
|
if (!needsToMigrate(srcDeviceState, destDeviceState)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
copyTable(source, TABLE_NAME, target.getWritableDatabase(), TMP_TABLE, context);
|
|
||||||
|
|
||||||
HashSet<String> validPackages = getValidPackages(context);
|
HashSet<String> validPackages = getValidPackages(context);
|
||||||
|
|
||||||
|
if (migrateForPreview) {
|
||||||
|
if (!LauncherSettings.Settings.call(
|
||||||
|
context.getContentResolver(),
|
||||||
|
LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW,
|
||||||
|
destDeviceState.getDbFile()).getBoolean(
|
||||||
|
LauncherSettings.Settings.EXTRA_VALUE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!LauncherSettings.Settings.call(
|
||||||
|
context.getContentResolver(),
|
||||||
|
LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER,
|
||||||
|
destDeviceState.getDbFile()).getBoolean(
|
||||||
|
LauncherSettings.Settings.EXTRA_VALUE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
long migrationStartTime = System.currentTimeMillis();
|
long migrationStartTime = System.currentTimeMillis();
|
||||||
try (SQLiteTransaction t = new SQLiteTransaction(target.getWritableDatabase())) {
|
try (SQLiteTransaction t = (SQLiteTransaction) LauncherSettings.Settings.call(
|
||||||
DbReader srcReader = new DbReader(t.getDb(), TMP_TABLE, context, validPackages);
|
context.getContentResolver(),
|
||||||
DbReader destReader = new DbReader(t.getDb(), TABLE_NAME, context, validPackages);
|
LauncherSettings.Settings.METHOD_NEW_TRANSACTION).getBinder(
|
||||||
|
LauncherSettings.Settings.EXTRA_VALUE)) {
|
||||||
|
|
||||||
|
DbReader srcReader = new DbReader(t.getDb(),
|
||||||
|
migrateForPreview ? LauncherSettings.Favorites.TABLE_NAME
|
||||||
|
: LauncherSettings.Favorites.TMP_TABLE,
|
||||||
|
context, validPackages);
|
||||||
|
DbReader destReader = new DbReader(t.getDb(),
|
||||||
|
migrateForPreview ? LauncherSettings.Favorites.PREVIEW_TABLE_NAME
|
||||||
|
: LauncherSettings.Favorites.TABLE_NAME,
|
||||||
|
context, validPackages);
|
||||||
|
|
||||||
Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
|
Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
|
||||||
migrate(target, srcReader, destReader, destDeviceState.getNumHotseat(),
|
migrate(context, t.getDb(), srcReader, destReader, destDeviceState.getNumHotseat(),
|
||||||
targetSize, srcDeviceState, destDeviceState);
|
targetSize, srcDeviceState, destDeviceState);
|
||||||
dropTable(t.getDb(), TMP_TABLE);
|
|
||||||
|
if (!migrateForPreview) {
|
||||||
|
dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
|
||||||
|
}
|
||||||
|
|
||||||
t.commit();
|
t.commit();
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -133,7 +174,7 @@ public class GridSizeMigrationUtil {
|
|||||||
Log.v(TAG, "Workspace migration completed in "
|
Log.v(TAG, "Workspace migration completed in "
|
||||||
+ (System.currentTimeMillis() - migrationStartTime));
|
+ (System.currentTimeMillis() - migrationStartTime));
|
||||||
|
|
||||||
if (!(context instanceof SandboxContext)) {
|
if (!migrateForPreview) {
|
||||||
// Save current configuration, so that the migration does not run again.
|
// Save current configuration, so that the migration does not run again.
|
||||||
destDeviceState.writeToPrefs(context);
|
destDeviceState.writeToPrefs(context);
|
||||||
}
|
}
|
||||||
@@ -141,7 +182,7 @@ public class GridSizeMigrationUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean migrate(
|
public static boolean migrate(
|
||||||
@NonNull DatabaseHelper helper,
|
@NonNull final Context context, @NonNull final SQLiteDatabase db,
|
||||||
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
|
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
|
||||||
final int destHotseatSize, @NonNull final Point targetSize,
|
final int destHotseatSize, @NonNull final Point targetSize,
|
||||||
@NonNull final DeviceGridState srcDeviceState,
|
@NonNull final DeviceGridState srcDeviceState,
|
||||||
@@ -193,8 +234,8 @@ public class GridSizeMigrationUtil {
|
|||||||
Collections.sort(workspaceToBeAdded);
|
Collections.sort(workspaceToBeAdded);
|
||||||
|
|
||||||
// Migrate hotseat
|
// Migrate hotseat
|
||||||
solveHotseatPlacement(helper, destHotseatSize,
|
solveHotseatPlacement(db, srcReader,
|
||||||
srcReader, destReader, dstHotseatItems, hotseatToBeAdded);
|
destReader, context, destHotseatSize, dstHotseatItems, hotseatToBeAdded);
|
||||||
|
|
||||||
// Migrate workspace.
|
// Migrate workspace.
|
||||||
// First we create a collection of the screens
|
// First we create a collection of the screens
|
||||||
@@ -214,8 +255,8 @@ public class GridSizeMigrationUtil {
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "Migrating " + screenId);
|
Log.d(TAG, "Migrating " + screenId);
|
||||||
}
|
}
|
||||||
solveGridPlacement(helper, srcReader,
|
solveGridPlacement(db, srcReader,
|
||||||
destReader, screenId, trgX, trgY, workspaceToBeAdded, false);
|
destReader, context, screenId, trgX, trgY, workspaceToBeAdded, false);
|
||||||
if (workspaceToBeAdded.isEmpty()) {
|
if (workspaceToBeAdded.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -225,8 +266,8 @@ public class GridSizeMigrationUtil {
|
|||||||
// any of the screens, in this case we add them to new screens until all of them are placed.
|
// any of the screens, in this case we add them to new screens until all of them are placed.
|
||||||
int screenId = destReader.mLastScreenId + 1;
|
int screenId = destReader.mLastScreenId + 1;
|
||||||
while (!workspaceToBeAdded.isEmpty()) {
|
while (!workspaceToBeAdded.isEmpty()) {
|
||||||
solveGridPlacement(helper, srcReader,
|
solveGridPlacement(db, srcReader,
|
||||||
destReader, screenId, trgX, trgY, workspaceToBeAdded, preservePages);
|
destReader, context, screenId, trgX, trgY, workspaceToBeAdded, preservePages);
|
||||||
screenId++;
|
screenId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,33 +298,33 @@ public class GridSizeMigrationUtil {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void insertEntryInDb(DatabaseHelper helper, DbEntry entry,
|
private static void insertEntryInDb(SQLiteDatabase db, Context context, DbEntry entry,
|
||||||
String srcTableName, String destTableName) {
|
String srcTableName, String destTableName) {
|
||||||
int id = copyEntryAndUpdate(helper, entry, srcTableName, destTableName);
|
int id = copyEntryAndUpdate(db, context, entry, srcTableName, destTableName);
|
||||||
|
|
||||||
if (entry.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
|
if (entry.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
|
||||||
for (Set<Integer> itemIds : entry.mFolderItems.values()) {
|
for (Set<Integer> itemIds : entry.mFolderItems.values()) {
|
||||||
for (int itemId : itemIds) {
|
for (int itemId : itemIds) {
|
||||||
copyEntryAndUpdate(helper, itemId, id, srcTableName, destTableName);
|
copyEntryAndUpdate(db, context, itemId, id, srcTableName, destTableName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int copyEntryAndUpdate(DatabaseHelper helper,
|
private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
|
||||||
DbEntry entry, String srcTableName, String destTableName) {
|
DbEntry entry, String srcTableName, String destTableName) {
|
||||||
return copyEntryAndUpdate(helper, entry, -1, -1, srcTableName, destTableName);
|
return copyEntryAndUpdate(db, context, entry, -1, -1, srcTableName, destTableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int copyEntryAndUpdate(DatabaseHelper helper,
|
private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
|
||||||
int id, int folderId, String srcTableName, String destTableName) {
|
int id, int folderId, String srcTableName, String destTableName) {
|
||||||
return copyEntryAndUpdate(helper, null, id, folderId, srcTableName, destTableName);
|
return copyEntryAndUpdate(db, context, null, id, folderId, srcTableName, destTableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int copyEntryAndUpdate(DatabaseHelper helper, DbEntry entry,
|
private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
|
||||||
int id, int folderId, String srcTableName, String destTableName) {
|
DbEntry entry, int id, int folderId, String srcTableName, String destTableName) {
|
||||||
int newId = -1;
|
int newId = -1;
|
||||||
Cursor c = helper.getWritableDatabase().query(srcTableName, null,
|
Cursor c = db.query(srcTableName, null,
|
||||||
LauncherSettings.Favorites._ID + " = '" + (entry != null ? entry.id : id) + "'",
|
LauncherSettings.Favorites._ID + " = '" + (entry != null ? entry.id : id) + "'",
|
||||||
null, null, null, null);
|
null, null, null, null);
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
@@ -294,9 +335,11 @@ public class GridSizeMigrationUtil {
|
|||||||
} else {
|
} else {
|
||||||
values.put(LauncherSettings.Favorites.CONTAINER, folderId);
|
values.put(LauncherSettings.Favorites.CONTAINER, folderId);
|
||||||
}
|
}
|
||||||
newId = helper.generateNewItemId();
|
newId = LauncherSettings.Settings.call(context.getContentResolver(),
|
||||||
|
LauncherSettings.Settings.METHOD_NEW_ITEM_ID).getInt(
|
||||||
|
LauncherSettings.Settings.EXTRA_VALUE);
|
||||||
values.put(LauncherSettings.Favorites._ID, newId);
|
values.put(LauncherSettings.Favorites._ID, newId);
|
||||||
helper.getWritableDatabase().insert(destTableName, null, values);
|
db.insert(destTableName, null, values);
|
||||||
}
|
}
|
||||||
c.close();
|
c.close();
|
||||||
return newId;
|
return newId;
|
||||||
@@ -324,9 +367,9 @@ public class GridSizeMigrationUtil {
|
|||||||
return validPackages;
|
return validPackages;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void solveGridPlacement(@NonNull final DatabaseHelper helper,
|
private static void solveGridPlacement(@NonNull final SQLiteDatabase db,
|
||||||
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
|
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
|
||||||
final int screenId, final int trgX, final int trgY,
|
@NonNull final Context context, final int screenId, final int trgX, final int trgY,
|
||||||
@NonNull final List<DbEntry> sortedItemsToPlace, final boolean matchingScreenIdOnly) {
|
@NonNull final List<DbEntry> sortedItemsToPlace, final boolean matchingScreenIdOnly) {
|
||||||
final GridOccupancy occupied = new GridOccupancy(trgX, trgY);
|
final GridOccupancy occupied = new GridOccupancy(trgX, trgY);
|
||||||
final Point trg = new Point(trgX, trgY);
|
final Point trg = new Point(trgX, trgY);
|
||||||
@@ -348,7 +391,7 @@ public class GridSizeMigrationUtil {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (findPlacementForEntry(entry, next, trg, occupied, screenId)) {
|
if (findPlacementForEntry(entry, next, trg, occupied, screenId)) {
|
||||||
insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName);
|
insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -385,9 +428,9 @@ public class GridSizeMigrationUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void solveHotseatPlacement(
|
private static void solveHotseatPlacement(@NonNull final SQLiteDatabase db,
|
||||||
@NonNull final DatabaseHelper helper, final int hotseatSize,
|
|
||||||
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
|
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
|
||||||
|
@NonNull final Context context, final int hotseatSize,
|
||||||
@NonNull final List<DbEntry> placedHotseatItems,
|
@NonNull final List<DbEntry> placedHotseatItems,
|
||||||
@NonNull final List<DbEntry> itemsToPlace) {
|
@NonNull final List<DbEntry> itemsToPlace) {
|
||||||
|
|
||||||
@@ -404,7 +447,7 @@ public class GridSizeMigrationUtil {
|
|||||||
// to something other than -1.
|
// to something other than -1.
|
||||||
entry.cellX = i;
|
entry.cellX = i;
|
||||||
entry.cellY = 0;
|
entry.cellY = 0;
|
||||||
insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName);
|
insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
|
||||||
occupied[entry.screenId] = true;
|
occupied[entry.screenId] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,16 @@
|
|||||||
|
|
||||||
package com.android.launcher3.model;
|
package com.android.launcher3.model;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
|
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.LauncherActivityInfo;
|
import android.content.pm.LauncherActivityInfo;
|
||||||
import android.content.pm.LauncherApps;
|
import android.content.pm.LauncherApps;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.CursorWrapper;
|
import android.database.CursorWrapper;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -66,7 +66,9 @@ public class LoaderCursor extends CursorWrapper {
|
|||||||
private final LongSparseArray<UserHandle> allUsers;
|
private final LongSparseArray<UserHandle> allUsers;
|
||||||
|
|
||||||
private final LauncherAppState mApp;
|
private final LauncherAppState mApp;
|
||||||
|
private final Uri mContentUri;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
private final PackageManager mPM;
|
||||||
private final IconCache mIconCache;
|
private final IconCache mIconCache;
|
||||||
private final InvariantDeviceProfile mIDP;
|
private final InvariantDeviceProfile mIDP;
|
||||||
|
|
||||||
@@ -106,14 +108,17 @@ public class LoaderCursor extends CursorWrapper {
|
|||||||
public int itemType;
|
public int itemType;
|
||||||
public int restoreFlag;
|
public int restoreFlag;
|
||||||
|
|
||||||
public LoaderCursor(Cursor cursor, LauncherAppState app, UserManagerState userManagerState) {
|
public LoaderCursor(Cursor cursor, Uri contentUri, LauncherAppState app,
|
||||||
|
UserManagerState userManagerState) {
|
||||||
super(cursor);
|
super(cursor);
|
||||||
|
|
||||||
mApp = app;
|
mApp = app;
|
||||||
allUsers = userManagerState.allUsers;
|
allUsers = userManagerState.allUsers;
|
||||||
|
mContentUri = contentUri;
|
||||||
mContext = app.getContext();
|
mContext = app.getContext();
|
||||||
mIconCache = app.getIconCache();
|
mIconCache = app.getIconCache();
|
||||||
mIDP = app.getInvariantDeviceProfile();
|
mIDP = app.getInvariantDeviceProfile();
|
||||||
|
mPM = mContext.getPackageManager();
|
||||||
|
|
||||||
// Init column indices
|
// Init column indices
|
||||||
mIconIndex = getColumnIndexOrThrow(Favorites.ICON);
|
mIconIndex = getColumnIndexOrThrow(Favorites.ICON);
|
||||||
@@ -385,7 +390,7 @@ public class LoaderCursor extends CursorWrapper {
|
|||||||
*/
|
*/
|
||||||
public ContentWriter updater() {
|
public ContentWriter updater() {
|
||||||
return new ContentWriter(mContext, new ContentWriter.CommitParams(
|
return new ContentWriter(mContext, new ContentWriter.CommitParams(
|
||||||
mApp.getModel().getModelDbController(),
|
mApp.getModel().getModelDbController().getDatabaseHelper(),
|
||||||
BaseColumns._ID + "= ?", new String[]{Integer.toString(id)}));
|
BaseColumns._ID + "= ?", new String[]{Integer.toString(id)}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,8 +409,8 @@ public class LoaderCursor extends CursorWrapper {
|
|||||||
public boolean commitDeleted() {
|
public boolean commitDeleted() {
|
||||||
if (mItemsToRemove.size() > 0) {
|
if (mItemsToRemove.size() > 0) {
|
||||||
// Remove dead items
|
// Remove dead items
|
||||||
mApp.getModel().getModelDbController().delete(TABLE_NAME,
|
mContext.getContentResolver().delete(mContentUri, Utilities.createDbSelectionQuery(
|
||||||
Utilities.createDbSelectionQuery(Favorites._ID, mItemsToRemove), null);
|
Favorites._ID, mItemsToRemove), null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -430,8 +435,9 @@ public class LoaderCursor extends CursorWrapper {
|
|||||||
// Update restored items that no longer require special handling
|
// Update restored items that no longer require special handling
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(Favorites.RESTORED, 0);
|
values.put(Favorites.RESTORED, 0);
|
||||||
mApp.getModel().getModelDbController().update(TABLE_NAME, values,
|
mContext.getContentResolver().update(mContentUri, values,
|
||||||
Utilities.createDbSelectionQuery(Favorites._ID, mRestoredRows), null);
|
Utilities.createDbSelectionQuery(
|
||||||
|
Favorites._ID, mRestoredRows), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.launcher3.model;
|
package com.android.launcher3.model;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
|
|
||||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
|
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
|
||||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
|
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
|
||||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
|
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
|
||||||
@@ -42,6 +41,7 @@ import android.content.pm.PackageInstaller.SessionInfo;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ShortcutInfo;
|
import android.content.pm.ShortcutInfo;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -50,6 +50,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.LongSparseArray;
|
import android.util.LongSparseArray;
|
||||||
|
import android.util.TimingLogger;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
@@ -199,10 +200,25 @@ public class LoaderTask implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
|
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
|
||||||
|
TimingLogger timingLogger = new TimingLogger(TAG, "run");
|
||||||
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
|
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
|
||||||
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
|
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
|
||||||
List<ShortcutInfo> allShortcuts = new ArrayList<>();
|
List<ShortcutInfo> allShortcuts = new ArrayList<>();
|
||||||
loadWorkspace(allShortcuts, "", memoryLogger);
|
Trace.beginSection("LoadWorkspace");
|
||||||
|
try {
|
||||||
|
loadWorkspace(allShortcuts, memoryLogger);
|
||||||
|
} finally {
|
||||||
|
Trace.endSection();
|
||||||
|
}
|
||||||
|
logASplit(timingLogger, "loadWorkspace");
|
||||||
|
|
||||||
|
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
|
||||||
|
verifyNotStopped();
|
||||||
|
mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
|
||||||
|
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
|
||||||
|
mModelDelegate.markActive();
|
||||||
|
logASplit(timingLogger, "workspaceDelegateItems");
|
||||||
|
}
|
||||||
|
|
||||||
// Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
|
// Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
|
||||||
// sanitizeData should not be invoked if the workspace is loaded from a db different
|
// sanitizeData should not be invoked if the workspace is loaded from a db different
|
||||||
@@ -212,21 +228,21 @@ public class LoaderTask implements Runnable {
|
|||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
sanitizeFolders(mItemsDeleted);
|
sanitizeFolders(mItemsDeleted);
|
||||||
sanitizeWidgetsShortcutsAndPackages();
|
sanitizeWidgetsShortcutsAndPackages();
|
||||||
logASplit("sanitizeData");
|
logASplit(timingLogger, "sanitizeData");
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
mLauncherBinder.bindWorkspace(true /* incrementBindId */, /* isBindSync= */ false);
|
mLauncherBinder.bindWorkspace(true /* incrementBindId */, /* isBindSync= */ false);
|
||||||
logASplit("bindWorkspace");
|
logASplit(timingLogger, "bindWorkspace");
|
||||||
|
|
||||||
mModelDelegate.workspaceLoadComplete();
|
mModelDelegate.workspaceLoadComplete();
|
||||||
// Notify the installer packages of packages with active installs on the first screen.
|
// Notify the installer packages of packages with active installs on the first screen.
|
||||||
sendFirstScreenActiveInstallsBroadcast();
|
sendFirstScreenActiveInstallsBroadcast();
|
||||||
logASplit("sendFirstScreenActiveInstallsBroadcast");
|
logASplit(timingLogger, "sendFirstScreenActiveInstallsBroadcast");
|
||||||
|
|
||||||
// Take a break
|
// Take a break
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
logASplit("step 1 complete");
|
logASplit(timingLogger, "step 1 complete");
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
|
|
||||||
// second step
|
// second step
|
||||||
@@ -237,16 +253,16 @@ public class LoaderTask implements Runnable {
|
|||||||
} finally {
|
} finally {
|
||||||
Trace.endSection();
|
Trace.endSection();
|
||||||
}
|
}
|
||||||
logASplit("loadAllApps");
|
logASplit(timingLogger, "loadAllApps");
|
||||||
|
|
||||||
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
|
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
|
||||||
mModelDelegate.loadAndBindAllAppsItems(mUserManagerState,
|
mModelDelegate.loadAndBindAllAppsItems(mUserManagerState,
|
||||||
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
|
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
|
||||||
logASplit("allAppsDelegateItems");
|
logASplit(timingLogger, "allAppsDelegateItems");
|
||||||
}
|
}
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
mLauncherBinder.bindAllApps();
|
mLauncherBinder.bindAllApps();
|
||||||
logASplit("bindAllApps");
|
logASplit(timingLogger, "bindAllApps");
|
||||||
|
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
|
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
|
||||||
@@ -254,73 +270,75 @@ public class LoaderTask implements Runnable {
|
|||||||
updateHandler.updateIcons(allActivityList,
|
updateHandler.updateIcons(allActivityList,
|
||||||
LauncherActivityCachingLogic.newInstance(mApp.getContext()),
|
LauncherActivityCachingLogic.newInstance(mApp.getContext()),
|
||||||
mApp.getModel()::onPackageIconsUpdated);
|
mApp.getModel()::onPackageIconsUpdated);
|
||||||
logASplit("update icon cache");
|
logASplit(timingLogger, "update icon cache");
|
||||||
|
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
logASplit("save shortcuts in icon cache");
|
logASplit(timingLogger, "save shortcuts in icon cache");
|
||||||
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
|
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
|
||||||
mApp.getModel()::onPackageIconsUpdated);
|
mApp.getModel()::onPackageIconsUpdated);
|
||||||
|
|
||||||
// Take a break
|
// Take a break
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
logASplit("step 2 complete");
|
logASplit(timingLogger, "step 2 complete");
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
|
|
||||||
// third step
|
// third step
|
||||||
List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
|
List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
|
||||||
logASplit("loadDeepShortcuts");
|
logASplit(timingLogger, "loadDeepShortcuts");
|
||||||
|
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
mLauncherBinder.bindDeepShortcuts();
|
mLauncherBinder.bindDeepShortcuts();
|
||||||
logASplit("bindDeepShortcuts");
|
logASplit(timingLogger, "bindDeepShortcuts");
|
||||||
|
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
logASplit("save deep shortcuts in icon cache");
|
logASplit(timingLogger, "save deep shortcuts in icon cache");
|
||||||
updateHandler.updateIcons(allDeepShortcuts,
|
updateHandler.updateIcons(allDeepShortcuts,
|
||||||
new ShortcutCachingLogic(), (pkgs, user) -> { });
|
new ShortcutCachingLogic(), (pkgs, user) -> { });
|
||||||
|
|
||||||
// Take a break
|
// Take a break
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
logASplit("step 3 complete");
|
logASplit(timingLogger, "step 3 complete");
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
|
|
||||||
// fourth step
|
// fourth step
|
||||||
List<ComponentWithLabelAndIcon> allWidgetsList =
|
List<ComponentWithLabelAndIcon> allWidgetsList =
|
||||||
mBgDataModel.widgetsModel.update(mApp, null);
|
mBgDataModel.widgetsModel.update(mApp, null);
|
||||||
logASplit("load widgets");
|
logASplit(timingLogger, "load widgets");
|
||||||
|
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
mLauncherBinder.bindWidgets();
|
mLauncherBinder.bindWidgets();
|
||||||
logASplit("bindWidgets");
|
logASplit(timingLogger, "bindWidgets");
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
|
|
||||||
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
|
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
|
||||||
mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);
|
mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);
|
||||||
logASplit("otherDelegateItems");
|
logASplit(timingLogger, "otherDelegateItems");
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHandler.updateIcons(allWidgetsList,
|
updateHandler.updateIcons(allWidgetsList,
|
||||||
new ComponentWithIconCachingLogic(mApp.getContext(), true),
|
new ComponentWithIconCachingLogic(mApp.getContext(), true),
|
||||||
mApp.getModel()::onWidgetLabelsUpdated);
|
mApp.getModel()::onWidgetLabelsUpdated);
|
||||||
logASplit("save widgets in icon cache");
|
logASplit(timingLogger, "save widgets in icon cache");
|
||||||
|
|
||||||
// fifth step
|
// fifth step
|
||||||
loadFolderNames();
|
loadFolderNames();
|
||||||
|
|
||||||
verifyNotStopped();
|
verifyNotStopped();
|
||||||
updateHandler.finish();
|
updateHandler.finish();
|
||||||
logASplit("finish icon update");
|
logASplit(timingLogger, "finish icon update");
|
||||||
|
|
||||||
mModelDelegate.modelLoadComplete();
|
mModelDelegate.modelLoadComplete();
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
memoryLogger.clearLogs();
|
memoryLogger.clearLogs();
|
||||||
} catch (CancellationException e) {
|
} catch (CancellationException e) {
|
||||||
// Loader stopped, ignore
|
// Loader stopped, ignore
|
||||||
logASplit("Cancelled");
|
logASplit(timingLogger, "Cancelled");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
memoryLogger.printLogs();
|
memoryLogger.printLogs();
|
||||||
throw e;
|
throw e;
|
||||||
|
} finally {
|
||||||
|
timingLogger.dumpToLog();
|
||||||
}
|
}
|
||||||
TraceHelper.INSTANCE.endSection(traceToken);
|
TraceHelper.INSTANCE.endSection(traceToken);
|
||||||
}
|
}
|
||||||
@@ -330,29 +348,25 @@ public class LoaderTask implements Runnable {
|
|||||||
this.notify();
|
this.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadWorkspace(
|
private void loadWorkspace(
|
||||||
List<ShortcutInfo> allDeepShortcuts,
|
List<ShortcutInfo> allDeepShortcuts, LoaderMemoryLogger memoryLogger) {
|
||||||
String selection,
|
loadWorkspace(allDeepShortcuts, Favorites.CONTENT_URI,
|
||||||
LoaderMemoryLogger memoryLogger) {
|
null /* selection */, memoryLogger);
|
||||||
Trace.beginSection("LoadWorkspace");
|
}
|
||||||
try {
|
|
||||||
loadWorkspaceImpl(allDeepShortcuts, selection, memoryLogger);
|
|
||||||
} finally {
|
|
||||||
Trace.endSection();
|
|
||||||
}
|
|
||||||
logASplit("loadWorkspace");
|
|
||||||
|
|
||||||
|
protected void loadWorkspaceForPreviewSurfaceRenderer(
|
||||||
|
List<ShortcutInfo> allDeepShortcuts, Uri contentUri, String selection) {
|
||||||
|
loadWorkspace(allDeepShortcuts, contentUri, selection, null);
|
||||||
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
|
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
|
||||||
verifyNotStopped();
|
|
||||||
mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
|
mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
|
||||||
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
|
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
|
||||||
mModelDelegate.markActive();
|
mModelDelegate.markActive();
|
||||||
logASplit("workspaceDelegateItems");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadWorkspaceImpl(
|
protected void loadWorkspace(
|
||||||
List<ShortcutInfo> allDeepShortcuts,
|
List<ShortcutInfo> allDeepShortcuts,
|
||||||
|
Uri contentUri,
|
||||||
String selection,
|
String selection,
|
||||||
@Nullable LoaderMemoryLogger memoryLogger) {
|
@Nullable LoaderMemoryLogger memoryLogger) {
|
||||||
final Context context = mApp.getContext();
|
final Context context = mApp.getContext();
|
||||||
@@ -363,7 +377,7 @@ public class LoaderTask implements Runnable {
|
|||||||
final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
|
final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
|
||||||
|
|
||||||
boolean clearDb = false;
|
boolean clearDb = false;
|
||||||
if (!mApp.getModel().getModelDbController().migrateGridIfNeeded()) {
|
if (!GridSizeMigrationUtil.migrateGridIfNeeded(context)) {
|
||||||
// Migration failed. Clear workspace.
|
// Migration failed. Clear workspace.
|
||||||
clearDb = true;
|
clearDb = true;
|
||||||
}
|
}
|
||||||
@@ -388,9 +402,8 @@ public class LoaderTask implements Runnable {
|
|||||||
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
|
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
|
||||||
|
|
||||||
mShortcutKeyToPinnedShortcuts = new HashMap<>();
|
mShortcutKeyToPinnedShortcuts = new HashMap<>();
|
||||||
ModelDbController dbController = mApp.getModel().getModelDbController();
|
|
||||||
final LoaderCursor c = new LoaderCursor(
|
final LoaderCursor c = new LoaderCursor(
|
||||||
dbController.query(TABLE_NAME, null, selection, null, null),
|
contentResolver.query(contentUri, null, selection, null, null), contentUri,
|
||||||
mApp, mUserManagerState);
|
mApp, mUserManagerState);
|
||||||
final Bundle extras = c.getExtras();
|
final Bundle extras = c.getExtras();
|
||||||
mDbName = extras == null ? null : extras.getString(Settings.EXTRA_DB_NAME);
|
mDbName = extras == null ? null : extras.getString(Settings.EXTRA_DB_NAME);
|
||||||
@@ -1099,9 +1112,12 @@ public class LoaderTask implements Runnable {
|
|||||||
FileLog.d(TAG, widgetDimension.toString());
|
FileLog.d(TAG, widgetDimension.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void logASplit(String label) {
|
private static void logASplit(@Nullable TimingLogger timingLogger, String label) {
|
||||||
if (DEBUG) {
|
if (timingLogger != null) {
|
||||||
Log.d(TAG, label);
|
timingLogger.addSplit(label);
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, label);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ import static android.util.Base64.NO_PADDING;
|
|||||||
import static android.util.Base64.NO_WRAP;
|
import static android.util.Base64.NO_WRAP;
|
||||||
|
|
||||||
import static com.android.launcher3.DefaultLayoutParser.RES_PARTNER_DEFAULT_LAYOUT;
|
import static com.android.launcher3.DefaultLayoutParser.RES_PARTNER_DEFAULT_LAYOUT;
|
||||||
import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb;
|
|
||||||
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY;
|
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY;
|
||||||
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL;
|
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL;
|
||||||
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG;
|
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG;
|
||||||
|
import static com.android.launcher3.model.DatabaseHelper.EMPTY_DATABASE_CREATED;
|
||||||
|
import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
|
||||||
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
|
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
|
||||||
|
|
||||||
import android.app.blob.BlobHandle;
|
import android.app.blob.BlobHandle;
|
||||||
@@ -30,6 +31,7 @@ import android.app.blob.BlobStoreManager;
|
|||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ProviderInfo;
|
import android.content.pm.ProviderInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@@ -41,7 +43,6 @@ import android.os.Binder;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -53,22 +54,18 @@ import androidx.annotation.WorkerThread;
|
|||||||
|
|
||||||
import com.android.launcher3.AutoInstallsLayout;
|
import com.android.launcher3.AutoInstallsLayout;
|
||||||
import com.android.launcher3.AutoInstallsLayout.SourceResources;
|
import com.android.launcher3.AutoInstallsLayout.SourceResources;
|
||||||
import com.android.launcher3.ConstantItem;
|
|
||||||
import com.android.launcher3.DefaultLayoutParser;
|
import com.android.launcher3.DefaultLayoutParser;
|
||||||
import com.android.launcher3.InvariantDeviceProfile;
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
import com.android.launcher3.LauncherAppState;
|
import com.android.launcher3.LauncherAppState;
|
||||||
import com.android.launcher3.LauncherFiles;
|
|
||||||
import com.android.launcher3.LauncherPrefs;
|
import com.android.launcher3.LauncherPrefs;
|
||||||
import com.android.launcher3.LauncherSettings;
|
import com.android.launcher3.LauncherSettings;
|
||||||
import com.android.launcher3.LauncherSettings.Favorites;
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.pm.UserCache;
|
|
||||||
import com.android.launcher3.provider.LauncherDbUtils;
|
import com.android.launcher3.provider.LauncherDbUtils;
|
||||||
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
|
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
|
||||||
import com.android.launcher3.provider.RestoreDbTask;
|
import com.android.launcher3.provider.RestoreDbTask;
|
||||||
import com.android.launcher3.util.IOUtils;
|
import com.android.launcher3.util.IOUtils;
|
||||||
import com.android.launcher3.util.IntArray;
|
import com.android.launcher3.util.IntArray;
|
||||||
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
|
|
||||||
import com.android.launcher3.util.Partner;
|
import com.android.launcher3.util.Partner;
|
||||||
import com.android.launcher3.widget.LauncherWidgetHolder;
|
import com.android.launcher3.widget.LauncherWidgetHolder;
|
||||||
|
|
||||||
@@ -76,6 +73,7 @@ import org.xmlpull.v1.XmlPullParser;
|
|||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class which maintains an instance of Launcher database and provides utility methods
|
* Utility class which maintains an instance of Launcher database and provides utility methods
|
||||||
@@ -84,8 +82,6 @@ import java.io.StringReader;
|
|||||||
public class ModelDbController {
|
public class ModelDbController {
|
||||||
private static final String TAG = "LauncherProvider";
|
private static final String TAG = "LauncherProvider";
|
||||||
|
|
||||||
private static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
|
|
||||||
|
|
||||||
protected DatabaseHelper mOpenHelper;
|
protected DatabaseHelper mOpenHelper;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
@@ -96,36 +92,26 @@ public class ModelDbController {
|
|||||||
|
|
||||||
private synchronized void createDbIfNotExists() {
|
private synchronized void createDbIfNotExists() {
|
||||||
if (mOpenHelper == null) {
|
if (mOpenHelper == null) {
|
||||||
mOpenHelper = createDatabaseHelper(false /* forMigration */);
|
mOpenHelper = DatabaseHelper.createDatabaseHelper(
|
||||||
RestoreDbTask.restoreIfNeeded(mContext, this);
|
mContext, false /* forMigration */);
|
||||||
|
|
||||||
|
RestoreDbTask.restoreIfNeeded(mContext, mOpenHelper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DatabaseHelper createDatabaseHelper(boolean forMigration) {
|
private synchronized boolean prepForMigration(String dbFile, String targetTableName,
|
||||||
boolean isSandbox = mContext instanceof SandboxContext;
|
Supplier<DatabaseHelper> src, Supplier<DatabaseHelper> dst) {
|
||||||
String dbName = isSandbox ? null : InvariantDeviceProfile.INSTANCE.get(mContext).dbFile;
|
if (TextUtils.equals(dbFile, mOpenHelper.getDatabaseName())) {
|
||||||
|
Log.e(TAG, "prepForMigration - target db is same as current: " + dbFile);
|
||||||
// Set the flag for empty DB
|
return false;
|
||||||
Runnable onEmptyDbCreateCallback = forMigration ? () -> { }
|
|
||||||
: () -> LauncherPrefs.get(mContext).putSync(getEmptyDbCreatedKey(dbName).to(true));
|
|
||||||
|
|
||||||
DatabaseHelper databaseHelper = new DatabaseHelper(mContext, dbName,
|
|
||||||
this::getSerialNumberForUser, onEmptyDbCreateCallback);
|
|
||||||
// Table creation sometimes fails silently, which leads to a crash loop.
|
|
||||||
// This way, we will try to create a table every time after crash, so the device
|
|
||||||
// would eventually be able to recover.
|
|
||||||
if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) {
|
|
||||||
Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
|
|
||||||
// This operation is a no-op if the table already exists.
|
|
||||||
addTableToDb(databaseHelper.getWritableDatabase(),
|
|
||||||
getSerialNumberForUser(Process.myUserHandle()),
|
|
||||||
true /* optional */);
|
|
||||||
}
|
}
|
||||||
databaseHelper.mHotseatRestoreTableExists = tableExists(
|
|
||||||
databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
|
|
||||||
|
|
||||||
databaseHelper.initIds();
|
final DatabaseHelper helper = src.get();
|
||||||
return databaseHelper;
|
mOpenHelper = dst.get();
|
||||||
|
copyTable(helper.getReadableDatabase(), Favorites.TABLE_NAME,
|
||||||
|
mOpenHelper.getWritableDatabase(), targetTableName, mContext);
|
||||||
|
helper.close();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -281,38 +267,42 @@ public class ModelDbController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrates the DB if needed, and returns false if the migration failed
|
* Updates the current DB and copies all the existing data to the temp table
|
||||||
* and DB needs to be cleared.
|
* @param dbFile name of the target db file name
|
||||||
*/
|
*/
|
||||||
public boolean migrateGridIfNeeded() {
|
@WorkerThread
|
||||||
InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext);
|
public boolean updateCurrentOpenHelper(String dbFile) {
|
||||||
if (!GridSizeMigrationUtil.needsToMigrate(mContext, idp)) {
|
createDbIfNotExists();
|
||||||
return true;
|
return prepForMigration(
|
||||||
}
|
dbFile,
|
||||||
String targetDbName = new DeviceGridState(idp).getDbFile();
|
Favorites.TMP_TABLE,
|
||||||
if (TextUtils.equals(targetDbName, mOpenHelper.getDatabaseName())) {
|
() -> mOpenHelper,
|
||||||
// DB is same, ignore
|
() -> DatabaseHelper.createDatabaseHelper(
|
||||||
return true;
|
mContext, true /* forMigration */));
|
||||||
}
|
|
||||||
DatabaseHelper oldHelper = mOpenHelper;
|
|
||||||
mOpenHelper = (mContext instanceof SandboxContext) ? oldHelper
|
|
||||||
: createDatabaseHelper(true /* forMigration */);
|
|
||||||
try {
|
|
||||||
return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, idp, mOpenHelper,
|
|
||||||
oldHelper.getWritableDatabase());
|
|
||||||
} finally {
|
|
||||||
if (mOpenHelper != oldHelper) {
|
|
||||||
oldHelper.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the underlying model database
|
* Returns the current DatabaseHelper.
|
||||||
|
* Only for tests
|
||||||
*/
|
*/
|
||||||
public SQLiteDatabase getDb() {
|
@WorkerThread
|
||||||
|
public DatabaseHelper getDatabaseHelper() {
|
||||||
createDbIfNotExists();
|
createDbIfNotExists();
|
||||||
return mOpenHelper.getWritableDatabase();
|
return mOpenHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the DB for preview by copying all existing data to preview table
|
||||||
|
*/
|
||||||
|
@WorkerThread
|
||||||
|
public boolean prepareForPreview(String dbFile) {
|
||||||
|
createDbIfNotExists();
|
||||||
|
return prepForMigration(
|
||||||
|
dbFile,
|
||||||
|
Favorites.PREVIEW_TABLE_NAME,
|
||||||
|
() -> DatabaseHelper.createDatabaseHelper(
|
||||||
|
mContext, dbFile, true /* forMigration */),
|
||||||
|
() -> mOpenHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAddOrDeleteOp(SQLiteDatabase db) {
|
private void onAddOrDeleteOp(SQLiteDatabase db) {
|
||||||
@@ -355,7 +345,8 @@ public class ModelDbController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void clearFlagEmptyDbCreated() {
|
private void clearFlagEmptyDbCreated() {
|
||||||
LauncherPrefs.get(mContext).removeSync(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()));
|
LauncherPrefs.getPrefs(mContext).edit()
|
||||||
|
.remove(mOpenHelper.getKey(EMPTY_DATABASE_CREATED)).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -368,8 +359,9 @@ public class ModelDbController {
|
|||||||
@WorkerThread
|
@WorkerThread
|
||||||
public synchronized void loadDefaultFavoritesIfNecessary() {
|
public synchronized void loadDefaultFavoritesIfNecessary() {
|
||||||
createDbIfNotExists();
|
createDbIfNotExists();
|
||||||
|
SharedPreferences sp = LauncherPrefs.getPrefs(mContext);
|
||||||
|
|
||||||
if (LauncherPrefs.get(mContext).get(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()))) {
|
if (sp.getBoolean(mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false)) {
|
||||||
Log.d(TAG, "loading default workspace");
|
Log.d(TAG, "loading default workspace");
|
||||||
|
|
||||||
LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder();
|
LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder();
|
||||||
@@ -487,27 +479,4 @@ public class ModelDbController {
|
|||||||
return new DefaultLayoutParser(mContext, widgetHolder,
|
return new DefaultLayoutParser(mContext, widgetHolder,
|
||||||
mOpenHelper, mContext.getResources(), defaultLayout);
|
mOpenHelper, mContext.getResources(), defaultLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-composite given key in respect to database. If the current db is
|
|
||||||
* {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
|
|
||||||
* given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
|
|
||||||
* string will be "EMPTY_DATABASE_CREATED@minimal.db".
|
|
||||||
*/
|
|
||||||
private ConstantItem<Boolean> getEmptyDbCreatedKey(String dbName) {
|
|
||||||
if (mContext instanceof SandboxContext) {
|
|
||||||
return LauncherPrefs.nonRestorableItem(EMPTY_DATABASE_CREATED,
|
|
||||||
false /* default value */, false /* boot aware */);
|
|
||||||
}
|
|
||||||
String key = TextUtils.equals(dbName, LauncherFiles.LAUNCHER_DB)
|
|
||||||
? EMPTY_DATABASE_CREATED : EMPTY_DATABASE_CREATED + "@" + dbName;
|
|
||||||
return LauncherPrefs.backedUpItem(key, false /* default value */, false /* boot aware */);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the serial number for the provided user
|
|
||||||
*/
|
|
||||||
public long getSerialNumberForUser(UserHandle user) {
|
|
||||||
return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class LauncherDbUtils {
|
|||||||
UserManagerState ums = new UserManagerState();
|
UserManagerState ums = new UserManagerState();
|
||||||
ums.init(UserCache.INSTANCE.get(context),
|
ums.init(UserCache.INSTANCE.get(context),
|
||||||
context.getSystemService(UserManager.class));
|
context.getSystemService(UserManager.class));
|
||||||
LoaderCursor lc = new LoaderCursor(c, LauncherAppState.getInstance(context), ums);
|
LoaderCursor lc = new LoaderCursor(c, null, LauncherAppState.getInstance(context), ums);
|
||||||
IntSet deletedShortcuts = new IntSet();
|
IntSet deletedShortcuts = new IntSet();
|
||||||
|
|
||||||
while (lc.moveToNext()) {
|
while (lc.moveToNext()) {
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.launcher3.provider;
|
package com.android.launcher3.provider;
|
||||||
|
|
||||||
import static android.os.Process.myUserHandle;
|
|
||||||
|
|
||||||
import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY;
|
import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY;
|
||||||
import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
|
import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
|
||||||
import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS;
|
import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS;
|
||||||
@@ -49,8 +47,8 @@ import com.android.launcher3.LauncherPrefs;
|
|||||||
import com.android.launcher3.LauncherSettings.Favorites;
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.logging.FileLog;
|
import com.android.launcher3.logging.FileLog;
|
||||||
|
import com.android.launcher3.model.DatabaseHelper;
|
||||||
import com.android.launcher3.model.DeviceGridState;
|
import com.android.launcher3.model.DeviceGridState;
|
||||||
import com.android.launcher3.model.ModelDbController;
|
|
||||||
import com.android.launcher3.model.data.AppInfo;
|
import com.android.launcher3.model.data.AppInfo;
|
||||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||||
@@ -85,12 +83,12 @@ public class RestoreDbTask {
|
|||||||
/**
|
/**
|
||||||
* Tries to restore the backup DB if needed
|
* Tries to restore the backup DB if needed
|
||||||
*/
|
*/
|
||||||
public static void restoreIfNeeded(Context context, ModelDbController dbController) {
|
public static void restoreIfNeeded(Context context, DatabaseHelper helper) {
|
||||||
if (!isPending(context)) {
|
if (!isPending(context)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!performRestore(context, dbController)) {
|
if (!performRestore(context, helper)) {
|
||||||
dbController.createEmptyDB();
|
helper.createEmptyDB(helper.getWritableDatabase());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain InvariantDeviceProfile first before setting pending to false, so
|
// Obtain InvariantDeviceProfile first before setting pending to false, so
|
||||||
@@ -104,12 +102,12 @@ public class RestoreDbTask {
|
|||||||
idp.reinitializeAfterRestore(context);
|
idp.reinitializeAfterRestore(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean performRestore(Context context, ModelDbController controller) {
|
private static boolean performRestore(Context context, DatabaseHelper helper) {
|
||||||
SQLiteDatabase db = controller.getDb();
|
SQLiteDatabase db = helper.getWritableDatabase();
|
||||||
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
|
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
|
||||||
RestoreDbTask task = new RestoreDbTask();
|
RestoreDbTask task = new RestoreDbTask();
|
||||||
task.sanitizeDB(context, controller, db, new BackupManager(context));
|
task.sanitizeDB(context, helper, db, new BackupManager(context));
|
||||||
task.restoreAppWidgetIdsIfExists(context, controller);
|
task.restoreAppWidgetIdsIfExists(context, helper);
|
||||||
t.commit();
|
t.commit();
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -131,10 +129,10 @@ public class RestoreDbTask {
|
|||||||
* @return number of items deleted.
|
* @return number of items deleted.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected int sanitizeDB(Context context, ModelDbController controller, SQLiteDatabase db,
|
protected int sanitizeDB(Context context, DatabaseHelper helper, SQLiteDatabase db,
|
||||||
BackupManager backupManager) throws Exception {
|
BackupManager backupManager) throws Exception {
|
||||||
// Primary user ids
|
// Primary user ids
|
||||||
long myProfileId = controller.getSerialNumberForUser(myUserHandle());
|
long myProfileId = helper.getDefaultUserSerial();
|
||||||
long oldProfileId = getDefaultProfileId(db);
|
long oldProfileId = getDefaultProfileId(db);
|
||||||
LongSparseArray<Long> oldManagedProfileIds = getManagedProfileIds(db, oldProfileId);
|
LongSparseArray<Long> oldManagedProfileIds = getManagedProfileIds(db, oldProfileId);
|
||||||
LongSparseArray<Long> profileMapping = new LongSparseArray<>(oldManagedProfileIds.size()
|
LongSparseArray<Long> profileMapping = new LongSparseArray<>(oldManagedProfileIds.size()
|
||||||
@@ -146,7 +144,7 @@ public class RestoreDbTask {
|
|||||||
long oldManagedProfileId = oldManagedProfileIds.keyAt(i);
|
long oldManagedProfileId = oldManagedProfileIds.keyAt(i);
|
||||||
UserHandle user = getUserForAncestralSerialNumber(backupManager, oldManagedProfileId);
|
UserHandle user = getUserForAncestralSerialNumber(backupManager, oldManagedProfileId);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
long newManagedProfileId = controller.getSerialNumberForUser(user);
|
long newManagedProfileId = helper.getSerialNumberForUser(user);
|
||||||
profileMapping.put(oldManagedProfileId, newManagedProfileId);
|
profileMapping.put(oldManagedProfileId, newManagedProfileId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,7 +213,7 @@ public class RestoreDbTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Override shortcuts
|
// Override shortcuts
|
||||||
maybeOverrideShortcuts(context, controller, db, myProfileId);
|
maybeOverrideShortcuts(context, helper, db, myProfileId);
|
||||||
|
|
||||||
return itemsDeleted;
|
return itemsDeleted;
|
||||||
}
|
}
|
||||||
@@ -323,11 +321,11 @@ public class RestoreDbTask {
|
|||||||
.putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType()));
|
.putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restoreAppWidgetIdsIfExists(Context context, ModelDbController controller) {
|
private void restoreAppWidgetIdsIfExists(Context context, DatabaseHelper helper) {
|
||||||
LauncherPrefs lp = LauncherPrefs.get(context);
|
LauncherPrefs lp = LauncherPrefs.get(context);
|
||||||
if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) {
|
if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) {
|
||||||
AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID);
|
AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID);
|
||||||
AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, controller,
|
AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, helper,
|
||||||
IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(),
|
IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(),
|
||||||
IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(),
|
IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(),
|
||||||
host);
|
host);
|
||||||
@@ -345,7 +343,7 @@ public class RestoreDbTask {
|
|||||||
APP_WIDGET_IDS.to(IntArray.wrap(newIds).toConcatString()));
|
APP_WIDGET_IDS.to(IntArray.wrap(newIds).toConcatString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void maybeOverrideShortcuts(Context context, ModelDbController controller,
|
protected static void maybeOverrideShortcuts(Context context, DatabaseHelper helper,
|
||||||
SQLiteDatabase db, long currentUser) {
|
SQLiteDatabase db, long currentUser) {
|
||||||
Map<String, LauncherActivityInfo> activityOverrides = ApiWrapper.getActivityOverrides(
|
Map<String, LauncherActivityInfo> activityOverrides = ApiWrapper.getActivityOverrides(
|
||||||
context);
|
context);
|
||||||
@@ -369,7 +367,7 @@ public class RestoreDbTask {
|
|||||||
if (override != null) {
|
if (override != null) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(Favorites.PROFILE_ID,
|
values.put(Favorites.PROFILE_ID,
|
||||||
controller.getSerialNumberForUser(override.getUser()));
|
helper.getSerialNumberForUser(override.getUser()));
|
||||||
values.put(Favorites.INTENT, AppInfo.makeLaunchIntent(override).toUri(0));
|
values.put(Favorites.INTENT, AppInfo.makeLaunchIntent(override).toUri(0));
|
||||||
db.update(Favorites.TABLE_NAME, values, String.format("%s=?", Favorites._ID),
|
db.update(Favorites.TABLE_NAME, values, String.format("%s=?", Favorites._ID),
|
||||||
new String[]{String.valueOf(c.getInt(idIndex))});
|
new String[]{String.valueOf(c.getInt(idIndex))});
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import com.android.launcher3.LauncherSettings;
|
|||||||
import com.android.launcher3.LauncherSettings.Favorites;
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
import com.android.launcher3.icons.BitmapInfo;
|
import com.android.launcher3.icons.BitmapInfo;
|
||||||
import com.android.launcher3.icons.GraphicsUtils;
|
import com.android.launcher3.icons.GraphicsUtils;
|
||||||
import com.android.launcher3.model.ModelDbController;
|
import com.android.launcher3.model.DatabaseHelper;
|
||||||
import com.android.launcher3.pm.UserCache;
|
import com.android.launcher3.pm.UserCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,7 +106,7 @@ public class ContentWriter {
|
|||||||
|
|
||||||
public int commit() {
|
public int commit() {
|
||||||
if (mCommitParams != null) {
|
if (mCommitParams != null) {
|
||||||
mCommitParams.mDbController.update(
|
mCommitParams.mDatabaseHelper.getWritableDatabase().update(
|
||||||
Favorites.TABLE_NAME, getValues(mContext),
|
Favorites.TABLE_NAME, getValues(mContext),
|
||||||
mCommitParams.mWhere, mCommitParams.mSelectionArgs);
|
mCommitParams.mWhere, mCommitParams.mSelectionArgs);
|
||||||
}
|
}
|
||||||
@@ -115,12 +115,12 @@ public class ContentWriter {
|
|||||||
|
|
||||||
public static final class CommitParams {
|
public static final class CommitParams {
|
||||||
|
|
||||||
final ModelDbController mDbController;
|
final DatabaseHelper mDatabaseHelper;
|
||||||
final String mWhere;
|
final String mWhere;
|
||||||
final String[] mSelectionArgs;
|
final String[] mSelectionArgs;
|
||||||
|
|
||||||
public CommitParams(ModelDbController controller, String where, String[] selectionArgs) {
|
public CommitParams(DatabaseHelper helper, String where, String[] selectionArgs) {
|
||||||
mDbController = controller;
|
mDatabaseHelper = helper;
|
||||||
mWhere = where;
|
mWhere = where;
|
||||||
mSelectionArgs = selectionArgs;
|
mSelectionArgs = selectionArgs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import androidx.test.platform.app.InstrumentationRegistry;
|
|||||||
|
|
||||||
import com.android.launcher3.LauncherSettings.Favorites;
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.pm.UserCache;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -223,9 +222,7 @@ public class DbDowngradeHelperTest {
|
|||||||
private class MyDatabaseHelper extends DatabaseHelper {
|
private class MyDatabaseHelper extends DatabaseHelper {
|
||||||
|
|
||||||
MyDatabaseHelper() {
|
MyDatabaseHelper() {
|
||||||
super(mContext, DB_FILE,
|
super(mContext, DB_FILE, false);
|
||||||
UserCache.INSTANCE.get(mContext)::getSerialNumberForUser,
|
|
||||||
() -> { });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.launcher3.model
|
package com.android.launcher3.model
|
||||||
|
|
||||||
import android.content.ContentValues
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
@@ -24,7 +23,6 @@ import android.graphics.Point
|
|||||||
import android.os.Process
|
import android.os.Process
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import com.android.launcher3.InvariantDeviceProfile
|
import com.android.launcher3.InvariantDeviceProfile
|
||||||
import com.android.launcher3.LauncherPrefs
|
import com.android.launcher3.LauncherPrefs
|
||||||
import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
|
import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
|
||||||
@@ -33,7 +31,10 @@ import com.android.launcher3.config.FeatureFlags
|
|||||||
import com.android.launcher3.model.GridSizeMigrationUtil.DbReader
|
import com.android.launcher3.model.GridSizeMigrationUtil.DbReader
|
||||||
import com.android.launcher3.pm.UserCache
|
import com.android.launcher3.pm.UserCache
|
||||||
import com.android.launcher3.provider.LauncherDbUtils
|
import com.android.launcher3.provider.LauncherDbUtils
|
||||||
|
import com.android.launcher3.util.LauncherModelHelper
|
||||||
|
import com.android.launcher3.util.LauncherModelHelper.*
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@@ -42,12 +43,11 @@ import org.junit.runner.RunWith
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class GridSizeMigrationUtilTest {
|
class GridSizeMigrationUtilTest {
|
||||||
|
private lateinit var modelHelper: LauncherModelHelper
|
||||||
private lateinit var context: Context
|
private lateinit var context: Context
|
||||||
|
private lateinit var db: SQLiteDatabase
|
||||||
private lateinit var validPackages: Set<String>
|
private lateinit var validPackages: Set<String>
|
||||||
private lateinit var idp: InvariantDeviceProfile
|
private lateinit var idp: InvariantDeviceProfile
|
||||||
private lateinit var dbHelper: DatabaseHelper
|
|
||||||
private lateinit var db: SQLiteDatabase
|
|
||||||
private val testPackage1 = "com.android.launcher3.validpackage1"
|
private val testPackage1 = "com.android.launcher3.validpackage1"
|
||||||
private val testPackage2 = "com.android.launcher3.validpackage2"
|
private val testPackage2 = "com.android.launcher3.validpackage2"
|
||||||
private val testPackage3 = "com.android.launcher3.validpackage3"
|
private val testPackage3 = "com.android.launcher3.validpackage3"
|
||||||
@@ -61,17 +61,13 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
modelHelper = LauncherModelHelper()
|
||||||
dbHelper =
|
context = modelHelper.sandboxContext
|
||||||
DatabaseHelper(
|
db = modelHelper.provider.db
|
||||||
context,
|
|
||||||
null,
|
|
||||||
UserCache.INSTANCE.get(context)::getSerialNumberForUser
|
|
||||||
) {}
|
|
||||||
db = dbHelper.writableDatabase
|
|
||||||
|
|
||||||
validPackages =
|
validPackages =
|
||||||
setOf(
|
setOf(
|
||||||
|
TEST_PACKAGE,
|
||||||
testPackage1,
|
testPackage1,
|
||||||
testPackage2,
|
testPackage2,
|
||||||
testPackage3,
|
testPackage3,
|
||||||
@@ -90,6 +86,11 @@ class GridSizeMigrationUtilTest {
|
|||||||
addTableToDb(db, userSerial, false, TMP_TABLE)
|
addTableToDb(db, userSerial, false, TMP_TABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
modelHelper.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
|
* Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
|
||||||
* needed anymore
|
* needed anymore
|
||||||
@@ -98,26 +99,26 @@ class GridSizeMigrationUtilTest {
|
|||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testMigration() {
|
fun testMigration() {
|
||||||
// Src Hotseat icons
|
// Src Hotseat icons
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
|
modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
|
modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
|
||||||
// Src grid icons
|
// Src grid icons
|
||||||
// _ _ _ _ _
|
// _ _ _ _ _
|
||||||
// _ _ _ _ 5
|
// _ _ _ _ 5
|
||||||
// _ _ 6 _ 7
|
// _ _ 6 _ 7
|
||||||
// _ _ 8 _ 9
|
// _ _ 8 _ 9
|
||||||
// _ _ _ _ _
|
// _ _ _ _ _
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 3, testPackage9, 9, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 3, testPackage9, 9, TMP_CONTENT_URI)
|
||||||
|
|
||||||
// Dest hotseat icons
|
// Dest hotseat icons
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
|
modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2)
|
||||||
// Dest grid icons
|
// Dest grid icons
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage10)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage10)
|
||||||
|
|
||||||
idp.numDatabaseHotseatIcons = 4
|
idp.numDatabaseHotseatIcons = 4
|
||||||
idp.numColumns = 4
|
idp.numColumns = 4
|
||||||
@@ -125,7 +126,8 @@ class GridSizeMigrationUtilTest {
|
|||||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
srcReader,
|
srcReader,
|
||||||
destReader,
|
destReader,
|
||||||
idp.numDatabaseHotseatIcons,
|
idp.numDatabaseHotseatIcons,
|
||||||
@@ -136,13 +138,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check hotseat items
|
// Check hotseat items
|
||||||
var c =
|
var c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(SCREEN, INTENT),
|
arrayOf(SCREEN, INTENT),
|
||||||
"container=$CONTAINER_HOTSEAT",
|
"container=$CONTAINER_HOTSEAT",
|
||||||
null,
|
null,
|
||||||
SCREEN,
|
SCREEN,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -167,13 +168,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check workspace items
|
// Check workspace items
|
||||||
c =
|
c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(CELLX, CELLY, INTENT),
|
arrayOf(CELLX, CELLY, INTENT),
|
||||||
"container=$CONTAINER_DESKTOP",
|
"container=$CONTAINER_DESKTOP",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -209,30 +209,30 @@ class GridSizeMigrationUtilTest {
|
|||||||
fun testMigrationBackAndForth() {
|
fun testMigrationBackAndForth() {
|
||||||
// Hotseat items in grid A
|
// Hotseat items in grid A
|
||||||
// 1 2 _ 3 4
|
// 1 2 _ 3 4
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
|
modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
|
modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
|
||||||
// Workspace items in grid A
|
// Workspace items in grid A
|
||||||
// _ _ _ _ _
|
// _ _ _ _ _
|
||||||
// _ _ _ _ 5
|
// _ _ _ _ 5
|
||||||
// _ _ 6 _ 7
|
// _ _ 6 _ 7
|
||||||
// _ _ 8 _ _
|
// _ _ 8 _ _
|
||||||
// _ _ _ _ _
|
// _ _ _ _ _
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI)
|
||||||
|
|
||||||
// Hotseat items in grid B
|
// Hotseat items in grid B
|
||||||
// 2 _ _ _
|
// 2 _ _ _
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
|
modelHelper.addItem(SHORTCUT, 0, HOTSEAT, 0, 0, testPackage2)
|
||||||
// Workspace items in grid B
|
// Workspace items in grid B
|
||||||
// _ _ _ _
|
// _ _ _ _
|
||||||
// _ _ _ 10
|
// _ _ _ 10
|
||||||
// _ _ _ _
|
// _ _ _ _
|
||||||
// _ _ _ _
|
// _ _ _ _
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 3, testPackage10)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 3, testPackage10)
|
||||||
|
|
||||||
idp.numDatabaseHotseatIcons = 4
|
idp.numDatabaseHotseatIcons = 4
|
||||||
idp.numColumns = 4
|
idp.numColumns = 4
|
||||||
@@ -241,7 +241,8 @@ class GridSizeMigrationUtilTest {
|
|||||||
val readerGridB = DbReader(db, TABLE_NAME, context, validPackages)
|
val readerGridB = DbReader(db, TABLE_NAME, context, validPackages)
|
||||||
// migrate from A -> B
|
// migrate from A -> B
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
readerGridA,
|
readerGridA,
|
||||||
readerGridB,
|
readerGridB,
|
||||||
idp.numDatabaseHotseatIcons,
|
idp.numDatabaseHotseatIcons,
|
||||||
@@ -252,13 +253,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check hotseat items in grid B
|
// Check hotseat items in grid B
|
||||||
var c =
|
var c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(SCREEN, INTENT),
|
arrayOf(SCREEN, INTENT),
|
||||||
"container=$CONTAINER_HOTSEAT",
|
"container=$CONTAINER_HOTSEAT",
|
||||||
null,
|
null,
|
||||||
SCREEN,
|
SCREEN,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -272,13 +272,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check workspace items in grid B
|
// Check workspace items in grid B
|
||||||
c =
|
c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
||||||
"container=$CONTAINER_DESKTOP",
|
"container=$CONTAINER_DESKTOP",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -295,11 +294,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
assertThat(locMap[testPackage8]).isEqualTo(Triple(0, 3, 1))
|
assertThat(locMap[testPackage8]).isEqualTo(Triple(0, 3, 1))
|
||||||
|
|
||||||
// add item in B
|
// add item in B
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 2, testPackage9)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 2, testPackage9)
|
||||||
|
|
||||||
// migrate from B -> A
|
// migrate from B -> A
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
readerGridB,
|
readerGridB,
|
||||||
readerGridA,
|
readerGridA,
|
||||||
5,
|
5,
|
||||||
@@ -309,13 +309,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
)
|
)
|
||||||
// Check hotseat items in grid A
|
// Check hotseat items in grid A
|
||||||
c =
|
c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TMP_TABLE,
|
TMP_CONTENT_URI,
|
||||||
arrayOf(SCREEN, INTENT),
|
arrayOf(SCREEN, INTENT),
|
||||||
"container=$CONTAINER_HOTSEAT",
|
"container=$CONTAINER_HOTSEAT",
|
||||||
null,
|
null,
|
||||||
SCREEN,
|
SCREEN,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -329,13 +328,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check workspace items in grid A
|
// Check workspace items in grid A
|
||||||
c =
|
c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TMP_TABLE,
|
TMP_CONTENT_URI,
|
||||||
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
||||||
"container=$CONTAINER_DESKTOP",
|
"container=$CONTAINER_DESKTOP",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -356,11 +354,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
assertThat(locMap[testPackage9]).isEqualTo(Triple(0, 0, 2))
|
assertThat(locMap[testPackage9]).isEqualTo(Triple(0, 0, 2))
|
||||||
|
|
||||||
// remove item from B
|
// remove item from B
|
||||||
db.delete(TMP_TABLE, "$_ID=7", null)
|
modelHelper.deleteItem(7, TMP_TABLE)
|
||||||
|
|
||||||
// migrate from A -> B
|
// migrate from A -> B
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
readerGridA,
|
readerGridA,
|
||||||
readerGridB,
|
readerGridB,
|
||||||
idp.numDatabaseHotseatIcons,
|
idp.numDatabaseHotseatIcons,
|
||||||
@@ -371,13 +370,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check hotseat items in grid B
|
// Check hotseat items in grid B
|
||||||
c =
|
c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(SCREEN, INTENT),
|
arrayOf(SCREEN, INTENT),
|
||||||
"container=$CONTAINER_HOTSEAT",
|
"container=$CONTAINER_HOTSEAT",
|
||||||
null,
|
null,
|
||||||
SCREEN,
|
SCREEN,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -391,13 +389,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check workspace items in grid B
|
// Check workspace items in grid B
|
||||||
c =
|
c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
||||||
"container=$CONTAINER_DESKTOP",
|
"container=$CONTAINER_DESKTOP",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -446,28 +443,10 @@ class GridSizeMigrationUtilTest {
|
|||||||
fun migrateToLargerHotseat() {
|
fun migrateToLargerHotseat() {
|
||||||
val srcHotseatItems =
|
val srcHotseatItems =
|
||||||
intArrayOf(
|
intArrayOf(
|
||||||
addItem(
|
modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
|
||||||
ITEM_TYPE_APPLICATION,
|
modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
|
||||||
0,
|
modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
|
||||||
CONTAINER_HOTSEAT,
|
modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
|
||||||
0,
|
|
||||||
0,
|
|
||||||
testPackage1,
|
|
||||||
1,
|
|
||||||
TMP_TABLE
|
|
||||||
),
|
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE),
|
|
||||||
addItem(
|
|
||||||
ITEM_TYPE_APPLICATION,
|
|
||||||
2,
|
|
||||||
CONTAINER_HOTSEAT,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
testPackage3,
|
|
||||||
3,
|
|
||||||
TMP_TABLE
|
|
||||||
),
|
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
|
|
||||||
)
|
)
|
||||||
val numSrcDatabaseHotseatIcons = srcHotseatItems.size
|
val numSrcDatabaseHotseatIcons = srcHotseatItems.size
|
||||||
idp.numDatabaseHotseatIcons = 6
|
idp.numDatabaseHotseatIcons = 6
|
||||||
@@ -476,7 +455,8 @@ class GridSizeMigrationUtilTest {
|
|||||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
srcReader,
|
srcReader,
|
||||||
destReader,
|
destReader,
|
||||||
idp.numDatabaseHotseatIcons,
|
idp.numDatabaseHotseatIcons,
|
||||||
@@ -487,13 +467,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check hotseat items
|
// Check hotseat items
|
||||||
val c =
|
val c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(SCREEN, INTENT),
|
arrayOf(SCREEN, INTENT),
|
||||||
"container=$CONTAINER_HOTSEAT",
|
"container=$CONTAINER_HOTSEAT",
|
||||||
null,
|
null,
|
||||||
SCREEN,
|
SCREEN,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -522,11 +501,11 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun migrateFromLargerHotseat() {
|
fun migrateFromLargerHotseat() {
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
|
modelHelper.addItem(SHORTCUT, 2, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
|
modelHelper.addItem(SHORTCUT, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 5, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 5, HOTSEAT, 0, 0, testPackage5, 5, TMP_CONTENT_URI)
|
||||||
|
|
||||||
idp.numDatabaseHotseatIcons = 4
|
idp.numDatabaseHotseatIcons = 4
|
||||||
idp.numColumns = 4
|
idp.numColumns = 4
|
||||||
@@ -534,7 +513,8 @@ class GridSizeMigrationUtilTest {
|
|||||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
srcReader,
|
srcReader,
|
||||||
destReader,
|
destReader,
|
||||||
idp.numDatabaseHotseatIcons,
|
idp.numDatabaseHotseatIcons,
|
||||||
@@ -545,13 +525,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Check hotseat items
|
// Check hotseat items
|
||||||
val c =
|
val c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(SCREEN, INTENT),
|
arrayOf(SCREEN, INTENT),
|
||||||
"container=$CONTAINER_HOTSEAT",
|
"container=$CONTAINER_HOTSEAT",
|
||||||
null,
|
null,
|
||||||
SCREEN,
|
SCREEN,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -589,11 +568,11 @@ class GridSizeMigrationUtilTest {
|
|||||||
enableNewMigrationLogic("4,4")
|
enableNewMigrationLogic("4,4")
|
||||||
|
|
||||||
// Setup src grid
|
// Setup src grid
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage1, 5, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage1, 5, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage2, 6, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage2, 6, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 1, testPackage3, 7, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 1, testPackage3, 7, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 2, testPackage4, 8, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 2, testPackage4, 8, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 3, 3, testPackage5, 9, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 2, DESKTOP, 3, 3, testPackage5, 9, TMP_CONTENT_URI)
|
||||||
|
|
||||||
idp.numDatabaseHotseatIcons = 4
|
idp.numDatabaseHotseatIcons = 4
|
||||||
idp.numColumns = 6
|
idp.numColumns = 6
|
||||||
@@ -602,7 +581,8 @@ class GridSizeMigrationUtilTest {
|
|||||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
srcReader,
|
srcReader,
|
||||||
destReader,
|
destReader,
|
||||||
idp.numDatabaseHotseatIcons,
|
idp.numDatabaseHotseatIcons,
|
||||||
@@ -613,13 +593,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Get workspace items
|
// Get workspace items
|
||||||
val c =
|
val c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(INTENT, SCREEN),
|
arrayOf(INTENT, SCREEN),
|
||||||
"container=$CONTAINER_DESKTOP",
|
"container=$CONTAINER_DESKTOP",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -651,11 +630,11 @@ class GridSizeMigrationUtilTest {
|
|||||||
enableNewMigrationLogic("2,2")
|
enableNewMigrationLogic("2,2")
|
||||||
|
|
||||||
// Setup src grid
|
// Setup src grid
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI)
|
||||||
|
|
||||||
idp.numDatabaseHotseatIcons = 4
|
idp.numDatabaseHotseatIcons = 4
|
||||||
idp.numColumns = 5
|
idp.numColumns = 5
|
||||||
@@ -663,7 +642,8 @@ class GridSizeMigrationUtilTest {
|
|||||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
srcReader,
|
srcReader,
|
||||||
destReader,
|
destReader,
|
||||||
idp.numDatabaseHotseatIcons,
|
idp.numDatabaseHotseatIcons,
|
||||||
@@ -674,13 +654,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Get workspace items
|
// Get workspace items
|
||||||
val c =
|
val c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(INTENT, SCREEN),
|
arrayOf(INTENT, SCREEN),
|
||||||
"container=$CONTAINER_DESKTOP",
|
"container=$CONTAINER_DESKTOP",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -712,11 +691,11 @@ class GridSizeMigrationUtilTest {
|
|||||||
enableNewMigrationLogic("5,5")
|
enableNewMigrationLogic("5,5")
|
||||||
|
|
||||||
// Setup src grid
|
// Setup src grid
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI)
|
||||||
addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE)
|
modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI)
|
||||||
|
|
||||||
idp.numDatabaseHotseatIcons = 4
|
idp.numDatabaseHotseatIcons = 4
|
||||||
idp.numColumns = 4
|
idp.numColumns = 4
|
||||||
@@ -724,7 +703,8 @@ class GridSizeMigrationUtilTest {
|
|||||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||||
GridSizeMigrationUtil.migrate(
|
GridSizeMigrationUtil.migrate(
|
||||||
dbHelper,
|
context,
|
||||||
|
db,
|
||||||
srcReader,
|
srcReader,
|
||||||
destReader,
|
destReader,
|
||||||
idp.numDatabaseHotseatIcons,
|
idp.numDatabaseHotseatIcons,
|
||||||
@@ -735,13 +715,12 @@ class GridSizeMigrationUtilTest {
|
|||||||
|
|
||||||
// Get workspace items
|
// Get workspace items
|
||||||
val c =
|
val c =
|
||||||
db.query(
|
context.contentResolver.query(
|
||||||
TABLE_NAME,
|
CONTENT_URI,
|
||||||
arrayOf(INTENT, SCREEN),
|
arrayOf(INTENT, SCREEN),
|
||||||
"container=$CONTAINER_DESKTOP",
|
"container=$CONTAINER_DESKTOP",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
?: throw IllegalStateException()
|
?: throw IllegalStateException()
|
||||||
@@ -768,48 +747,4 @@ class GridSizeMigrationUtilTest {
|
|||||||
private fun enableNewMigrationLogic(srcGridSize: String) {
|
private fun enableNewMigrationLogic(srcGridSize: String) {
|
||||||
LauncherPrefs.get(context).putSync(WORKSPACE_SIZE.to(srcGridSize))
|
LauncherPrefs.get(context).putSync(WORKSPACE_SIZE.to(srcGridSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addItem(
|
|
||||||
type: Int,
|
|
||||||
screen: Int,
|
|
||||||
container: Int,
|
|
||||||
x: Int,
|
|
||||||
y: Int,
|
|
||||||
packageName: String?
|
|
||||||
): Int {
|
|
||||||
return addItem(
|
|
||||||
type,
|
|
||||||
screen,
|
|
||||||
container,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
packageName,
|
|
||||||
dbHelper.generateNewItemId(),
|
|
||||||
TABLE_NAME
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addItem(
|
|
||||||
type: Int,
|
|
||||||
screen: Int,
|
|
||||||
container: Int,
|
|
||||||
x: Int,
|
|
||||||
y: Int,
|
|
||||||
packageName: String?,
|
|
||||||
id: Int,
|
|
||||||
tableName: String
|
|
||||||
): Int {
|
|
||||||
val values = ContentValues()
|
|
||||||
values.put(_ID, id)
|
|
||||||
values.put(CONTAINER, container)
|
|
||||||
values.put(SCREEN, screen)
|
|
||||||
values.put(CELLX, x)
|
|
||||||
values.put(CELLY, y)
|
|
||||||
values.put(SPANX, 1)
|
|
||||||
values.put(SPANY, 1)
|
|
||||||
values.put(ITEM_TYPE, type)
|
|
||||||
values.put(INTENT, Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0))
|
|
||||||
db.insert(tableName, null, values)
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import androidx.test.filters.SmallTest;
|
|||||||
|
|
||||||
import com.android.launcher3.InvariantDeviceProfile;
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
import com.android.launcher3.LauncherAppState;
|
import com.android.launcher3.LauncherAppState;
|
||||||
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
import com.android.launcher3.model.data.ItemInfo;
|
import com.android.launcher3.model.data.ItemInfo;
|
||||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||||
import com.android.launcher3.util.Executors;
|
import com.android.launcher3.util.Executors;
|
||||||
@@ -101,7 +102,7 @@ public class LoaderCursorTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
UserManagerState ums = new UserManagerState();
|
UserManagerState ums = new UserManagerState();
|
||||||
mLoaderCursor = new LoaderCursor(mCursor, mApp, ums);
|
mLoaderCursor = new LoaderCursor(mCursor, Favorites.CONTENT_URI, mApp, ums);
|
||||||
ums.allUsers.put(0, Process.myUserHandle());
|
ums.allUsers.put(0, Process.myUserHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import com.android.launcher3.LauncherSettings.Favorites;
|
|||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.model.DatabaseHelper;
|
import com.android.launcher3.model.DatabaseHelper;
|
||||||
import com.android.launcher3.model.DbDowngradeHelper;
|
import com.android.launcher3.model.DbDowngradeHelper;
|
||||||
import com.android.launcher3.pm.UserCache;
|
|
||||||
import com.android.launcher3.settings.SettingsActivity;
|
import com.android.launcher3.settings.SettingsActivity;
|
||||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||||
import com.android.launcher3.util.IOUtils;
|
import com.android.launcher3.util.IOUtils;
|
||||||
@@ -166,11 +165,12 @@ public class LauncherDbUtilsTest {
|
|||||||
private class MyDatabaseHelper extends DatabaseHelper {
|
private class MyDatabaseHelper extends DatabaseHelper {
|
||||||
|
|
||||||
MyDatabaseHelper() {
|
MyDatabaseHelper() {
|
||||||
super(mContext, null, UserCache.INSTANCE.get(mContext)::getSerialNumberForUser,
|
super(mContext, null, false);
|
||||||
() -> { });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
|
protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
|
||||||
|
|
||||||
|
protected void onEmptyDbCreated() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ import com.android.launcher3.LauncherAppState;
|
|||||||
import com.android.launcher3.LauncherSettings;
|
import com.android.launcher3.LauncherSettings;
|
||||||
import com.android.launcher3.LauncherSettings.Favorites;
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
import com.android.launcher3.model.DatabaseHelper;
|
import com.android.launcher3.model.DatabaseHelper;
|
||||||
import com.android.launcher3.model.ModelDbController;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -64,13 +63,13 @@ public class RestoreDbTaskTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetProfileId() throws Exception {
|
public void testGetProfileId() throws Exception {
|
||||||
SQLiteDatabase db = new MyModelDbController(23).getDb();
|
SQLiteDatabase db = new MyDatabaseHelper(23).getWritableDatabase();
|
||||||
assertEquals(23, new RestoreDbTask().getDefaultProfileId(db));
|
assertEquals(23, new RestoreDbTask().getDefaultProfileId(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMigrateProfileId() throws Exception {
|
public void testMigrateProfileId() throws Exception {
|
||||||
SQLiteDatabase db = new MyModelDbController(42).getDb();
|
SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
|
||||||
// Add some mock data
|
// Add some mock data
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
@@ -90,7 +89,7 @@ public class RestoreDbTaskTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChangeDefaultColumn() throws Exception {
|
public void testChangeDefaultColumn() throws Exception {
|
||||||
SQLiteDatabase db = new MyModelDbController(42).getDb();
|
SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
|
||||||
// Add some mock data
|
// Add some mock data
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
@@ -121,20 +120,20 @@ public class RestoreDbTaskTest {
|
|||||||
long workProfileId = myProfileId + 2;
|
long workProfileId = myProfileId + 2;
|
||||||
long workProfileId_old = myProfileId + 3;
|
long workProfileId_old = myProfileId + 3;
|
||||||
|
|
||||||
MyModelDbController controller = new MyModelDbController(myProfileId);
|
MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId);
|
||||||
SQLiteDatabase db = controller.getDb();
|
SQLiteDatabase db = helper.getWritableDatabase();
|
||||||
BackupManager bm = spy(new BackupManager(context));
|
BackupManager bm = spy(new BackupManager(context));
|
||||||
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
|
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
|
||||||
doReturn(mWorkUser).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
|
doReturn(mWorkUser).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
|
||||||
controller.users.put(workProfileId, mWorkUser);
|
helper.users.put(workProfileId, mWorkUser);
|
||||||
|
|
||||||
addIconsBulk(controller, 10, 1, myProfileId_old);
|
addIconsBulk(helper, 10, 1, myProfileId_old);
|
||||||
addIconsBulk(controller, 6, 2, workProfileId_old);
|
addIconsBulk(helper, 6, 2, workProfileId_old);
|
||||||
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
|
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
|
||||||
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
|
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
|
||||||
|
|
||||||
RestoreDbTask task = new RestoreDbTask();
|
RestoreDbTask task = new RestoreDbTask();
|
||||||
task.sanitizeDB(context, controller, controller.getDb(), bm);
|
task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm);
|
||||||
|
|
||||||
// All the data has been migrated to the new user ids
|
// All the data has been migrated to the new user ids
|
||||||
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
|
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
|
||||||
@@ -152,20 +151,20 @@ public class RestoreDbTaskTest {
|
|||||||
long myProfileId_old = myProfileId + 1;
|
long myProfileId_old = myProfileId + 1;
|
||||||
long workProfileId_old = myProfileId + 3;
|
long workProfileId_old = myProfileId + 3;
|
||||||
|
|
||||||
MyModelDbController controller = new MyModelDbController(myProfileId);
|
MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId);
|
||||||
SQLiteDatabase db = controller.getDb();
|
SQLiteDatabase db = helper.getWritableDatabase();
|
||||||
BackupManager bm = spy(new BackupManager(context));
|
BackupManager bm = spy(new BackupManager(context));
|
||||||
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
|
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
|
||||||
// Work profile is not migrated
|
// Work profile is not migrated
|
||||||
doReturn(null).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
|
doReturn(null).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
|
||||||
|
|
||||||
addIconsBulk(controller, 10, 1, myProfileId_old);
|
addIconsBulk(helper, 10, 1, myProfileId_old);
|
||||||
addIconsBulk(controller, 6, 2, workProfileId_old);
|
addIconsBulk(helper, 6, 2, workProfileId_old);
|
||||||
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
|
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
|
||||||
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
|
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
|
||||||
|
|
||||||
RestoreDbTask task = new RestoreDbTask();
|
RestoreDbTask task = new RestoreDbTask();
|
||||||
task.sanitizeDB(context, controller, controller.getDb(), bm);
|
task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm);
|
||||||
|
|
||||||
// All the data has been migrated to the new user ids
|
// All the data has been migrated to the new user ids
|
||||||
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
|
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
|
||||||
@@ -174,13 +173,12 @@ public class RestoreDbTaskTest {
|
|||||||
assertEquals(10, getCount(db, "select * from favorites"));
|
assertEquals(10, getCount(db, "select * from favorites"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIconsBulk(MyModelDbController controller,
|
private void addIconsBulk(DatabaseHelper helper, int count, int screen, long profileId) {
|
||||||
int count, int screen, long profileId) {
|
|
||||||
int columns = LauncherAppState.getIDP(getInstrumentation().getTargetContext()).numColumns;
|
int columns = LauncherAppState.getIDP(getInstrumentation().getTargetContext()).numColumns;
|
||||||
String packageName = getInstrumentation().getContext().getPackageName();
|
String packageName = getInstrumentation().getContext().getPackageName();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(LauncherSettings.Favorites._ID, controller.generateNewItemId());
|
values.put(LauncherSettings.Favorites._ID, helper.generateNewItemId());
|
||||||
values.put(LauncherSettings.Favorites.CONTAINER, CONTAINER_DESKTOP);
|
values.put(LauncherSettings.Favorites.CONTAINER, CONTAINER_DESKTOP);
|
||||||
values.put(LauncherSettings.Favorites.SCREEN, screen);
|
values.put(LauncherSettings.Favorites.SCREEN, screen);
|
||||||
values.put(LauncherSettings.Favorites.CELLX, i % columns);
|
values.put(LauncherSettings.Favorites.CELLX, i % columns);
|
||||||
@@ -191,11 +189,11 @@ public class RestoreDbTaskTest {
|
|||||||
values.put(LauncherSettings.Favorites.ITEM_TYPE, ITEM_TYPE_APPLICATION);
|
values.put(LauncherSettings.Favorites.ITEM_TYPE, ITEM_TYPE_APPLICATION);
|
||||||
values.put(LauncherSettings.Favorites.INTENT,
|
values.put(LauncherSettings.Favorites.INTENT,
|
||||||
new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
|
new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
|
||||||
|
helper.getWritableDatabase().insert(TABLE_NAME, null, values);
|
||||||
controller.insert(TABLE_NAME, values);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveScreenIdGaps_firstScreenEmpty() {
|
public void testRemoveScreenIdGaps_firstScreenEmpty() {
|
||||||
runRemoveScreenIdGapsTest(
|
runRemoveScreenIdGapsTest(
|
||||||
@@ -218,7 +216,7 @@ public class RestoreDbTaskTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void runRemoveScreenIdGapsTest(int[] screenIds, int[] expectedScreenIds) {
|
private void runRemoveScreenIdGapsTest(int[] screenIds, int[] expectedScreenIds) {
|
||||||
SQLiteDatabase db = new MyModelDbController(42).getDb();
|
SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
|
||||||
// Add some mock data
|
// Add some mock data
|
||||||
for (int i = 0; i < screenIds.length; i++) {
|
for (int i = 0; i < screenIds.length; i++) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
@@ -256,15 +254,14 @@ public class RestoreDbTaskTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyModelDbController extends ModelDbController {
|
private class MyDatabaseHelper extends DatabaseHelper {
|
||||||
|
|
||||||
public final LongSparseArray<UserHandle> users = new LongSparseArray<>();
|
public final LongSparseArray<UserHandle> users;
|
||||||
|
|
||||||
MyModelDbController(long profileId) {
|
MyDatabaseHelper(long profileId) {
|
||||||
super(getInstrumentation().getTargetContext());
|
super(getInstrumentation().getTargetContext(), null, false);
|
||||||
|
users = new LongSparseArray<>();
|
||||||
users.put(profileId, myUserHandle());
|
users.put(profileId, myUserHandle());
|
||||||
mOpenHelper = new DatabaseHelper(getInstrumentation().getTargetContext(), null,
|
|
||||||
this::getSerialNumberForUser, () -> { });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -272,5 +269,10 @@ public class RestoreDbTaskTest {
|
|||||||
int index = users.indexOfValue(user);
|
int index = users.indexOfValue(user);
|
||||||
return index >= 0 ? users.keyAt(index) : -1;
|
return index >= 0 ? users.keyAt(index) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
|
||||||
|
|
||||||
|
protected void onEmptyDbCreated() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -363,6 +363,12 @@ public class LauncherModelHelper {
|
|||||||
sandboxContext.getContentResolver().insert(contentUri, values);
|
sandboxContext.getContentResolver().insert(contentUri, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteItem(int itemId, @NonNull final String tableName) {
|
||||||
|
final Uri uri = Uri.parse("content://"
|
||||||
|
+ LauncherProvider.AUTHORITY + "/" + tableName + "/" + itemId);
|
||||||
|
sandboxContext.getContentResolver().delete(uri, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up a mock provider to load the provided layout by default, next time the layout loads
|
* Sets up a mock provider to load the provided layout by default, next time the layout loads
|
||||||
*/
|
*/
|
||||||
@@ -420,7 +426,7 @@ public class LauncherModelHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SQLiteDatabase getDb() {
|
public SQLiteDatabase getDb() {
|
||||||
return getModelDbController().getDb();
|
return getModelDbController().getDatabaseHelper().getWritableDatabase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user