Merge "Refactor Workspace Loading / Processing code." into tm-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index ad6ce7d..2e1318b 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -112,10 +112,23 @@
}
@Override
- @WorkerThread
- public void loadItems(UserManagerState ums, Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
+ public void loadHotseatItems(UserManagerState ums,
+ Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
// TODO: Implement caching and preloading
- super.loadItems(ums, pinnedShortcuts);
+ super.loadHotseatItems(ums, pinnedShortcuts);
+
+ WorkspaceItemFactory hotseatFactory = new WorkspaceItemFactory(mApp, ums, pinnedShortcuts,
+ mIDP.numDatabaseHotseatIcons, mHotseatState.containerId);
+ FixedContainerItems hotseatItems = new FixedContainerItems(mHotseatState.containerId,
+ mHotseatState.storage.read(mApp.getContext(), hotseatFactory, ums.allUsers::get));
+ mDataModel.extraItems.put(mHotseatState.containerId, hotseatItems);
+ }
+
+ @Override
+ public void loadAllAppsItems(UserManagerState ums,
+ Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
+ // TODO: Implement caching and preloading
+ super.loadAllAppsItems(ums, pinnedShortcuts);
WorkspaceItemFactory allAppsFactory = new WorkspaceItemFactory(mApp, ums, pinnedShortcuts,
mIDP.numDatabaseAllAppsColumns, mAllAppsState.containerId);
@@ -123,17 +136,22 @@
mAllAppsState.containerId, mAllAppsState.storage.read(mApp.getContext(),
allAppsFactory, ums.allUsers::get));
mDataModel.extraItems.put(mAllAppsState.containerId, allAppsPredictionItems);
+ }
- WorkspaceItemFactory hotseatFactory = new WorkspaceItemFactory(mApp, ums, pinnedShortcuts,
- mIDP.numDatabaseHotseatIcons, mHotseatState.containerId);
- FixedContainerItems hotseatItems = new FixedContainerItems(mHotseatState.containerId,
- mHotseatState.storage.read(mApp.getContext(), hotseatFactory, ums.allUsers::get));
- mDataModel.extraItems.put(mHotseatState.containerId, hotseatItems);
+ @Override
+ public void loadWidgetsRecommendationItems() {
+ // TODO: Implement caching and preloading
+ super.loadWidgetsRecommendationItems();
// Widgets prediction isn't used frequently. And thus, it is not persisted on disk.
mDataModel.extraItems.put(mWidgetsRecommendationState.containerId,
new FixedContainerItems(mWidgetsRecommendationState.containerId,
new ArrayList<>()));
+ }
+
+ @Override
+ public void markActive() {
+ super.markActive();
mActive = true;
}
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 6c62b31..0a6a7cd 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -37,7 +37,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
@@ -72,24 +71,32 @@
private final IconCache mIconCache;
private final InvariantDeviceProfile mIDP;
- private final IntArray itemsToRemove = new IntArray();
- private final IntArray restoredRows = new IntArray();
- private final IntSparseArrayMap<GridOccupancy> occupied = new IntSparseArrayMap<>();
+ private final IntArray mItemsToRemove = new IntArray();
+ private final IntArray mRestoredRows = new IntArray();
+ private final IntSparseArrayMap<GridOccupancy> mOccupied = new IntSparseArrayMap<>();
- private final int iconPackageIndex;
- private final int iconResourceIndex;
- private final int iconIndex;
- public final int titleIndex;
+ private final int mIconPackageIndex;
+ private final int mIconResourceIndex;
+ private final int mIconIndex;
+ public final int mTitleIndex;
- private final int idIndex;
- private final int containerIndex;
- private final int itemTypeIndex;
- private final int screenIndex;
- private final int cellXIndex;
- private final int cellYIndex;
- private final int profileIdIndex;
- private final int restoredIndex;
- private final int intentIndex;
+ private final int mIdIndex;
+ private final int mContainerIndex;
+ private final int mItemTypeIndex;
+ private final int mScreenIndex;
+ private final int mCellXIndex;
+ private final int mCellYIndex;
+ private final int mProfileIdIndex;
+ private final int mRestoredIndex;
+ private final int mIntentIndex;
+
+ private final int mAppWidgetIdIndex;
+ private final int mAppWidgetProviderIndex;
+ private final int mSpanXIndex;
+ private final int mSpanYIndex;
+ private final int mRankIndex;
+ private final int mOptionsIndex;
+ private final int mAppWidgetSourceIndex;
@Nullable
private LauncherActivityInfo mActivityInfo;
@@ -114,20 +121,28 @@
mPM = mContext.getPackageManager();
// Init column indices
- iconIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
- iconPackageIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
- iconResourceIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
- titleIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+ mIconIndex = getColumnIndexOrThrow(Favorites.ICON);
+ mIconPackageIndex = getColumnIndexOrThrow(Favorites.ICON_PACKAGE);
+ mIconResourceIndex = getColumnIndexOrThrow(Favorites.ICON_RESOURCE);
+ mTitleIndex = getColumnIndexOrThrow(Favorites.TITLE);
- idIndex = getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
- containerIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
- itemTypeIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
- screenIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
- cellXIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
- cellYIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
- profileIdIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID);
- restoredIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.RESTORED);
- intentIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ mIdIndex = getColumnIndexOrThrow(Favorites._ID);
+ mContainerIndex = getColumnIndexOrThrow(Favorites.CONTAINER);
+ mItemTypeIndex = getColumnIndexOrThrow(Favorites.ITEM_TYPE);
+ mScreenIndex = getColumnIndexOrThrow(Favorites.SCREEN);
+ mCellXIndex = getColumnIndexOrThrow(Favorites.CELLX);
+ mCellYIndex = getColumnIndexOrThrow(Favorites.CELLY);
+ mProfileIdIndex = getColumnIndexOrThrow(Favorites.PROFILE_ID);
+ mRestoredIndex = getColumnIndexOrThrow(Favorites.RESTORED);
+ mIntentIndex = getColumnIndexOrThrow(Favorites.INTENT);
+
+ mAppWidgetIdIndex = getColumnIndexOrThrow(Favorites.APPWIDGET_ID);
+ mAppWidgetProviderIndex = getColumnIndexOrThrow(Favorites.APPWIDGET_PROVIDER);
+ mSpanXIndex = getColumnIndexOrThrow(Favorites.SPANX);
+ mSpanYIndex = getColumnIndexOrThrow(Favorites.SPANY);
+ mRankIndex = getColumnIndexOrThrow(Favorites.RANK);
+ mOptionsIndex = getColumnIndexOrThrow(Favorites.OPTIONS);
+ mAppWidgetSourceIndex = getColumnIndexOrThrow(Favorites.APPWIDGET_SOURCE);
}
@Override
@@ -137,18 +152,18 @@
mActivityInfo = null;
// Load common properties.
- itemType = getInt(itemTypeIndex);
- container = getInt(containerIndex);
- id = getInt(idIndex);
- serialNumber = getInt(profileIdIndex);
+ itemType = getInt(mItemTypeIndex);
+ container = getInt(mContainerIndex);
+ id = getInt(mIdIndex);
+ serialNumber = getInt(mProfileIdIndex);
user = allUsers.get(serialNumber);
- restoreFlag = getInt(restoredIndex);
+ restoreFlag = getInt(mRestoredIndex);
}
return result;
}
public Intent parseIntent() {
- String intentDescription = getString(intentIndex);
+ String intentDescription = getString(mIntentIndex);
try {
return TextUtils.isEmpty(intentDescription) ?
null : Intent.parseUri(intentDescription, 0);
@@ -185,14 +200,14 @@
public IconRequestInfo<WorkspaceItemInfo> createIconRequestInfo(
WorkspaceItemInfo wai, boolean useLowResIcon) {
- String packageName = itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
- ? getString(iconPackageIndex) : null;
- String resourceName = itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
- ? getString(iconResourceIndex) : null;
- byte[] iconBlob = itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+ String packageName = itemType == Favorites.ITEM_TYPE_SHORTCUT
+ ? getString(mIconPackageIndex) : null;
+ String resourceName = itemType == Favorites.ITEM_TYPE_SHORTCUT
+ ? getString(mIconResourceIndex) : null;
+ byte[] iconBlob = itemType == Favorites.ITEM_TYPE_SHORTCUT
|| itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
|| restoreFlag != 0
- ? getBlob(iconIndex) : null;
+ ? getBlob(mIconIndex) : null;
return new IconRequestInfo<>(
wai, mActivityInfo, packageName, resourceName, iconBlob, useLowResIcon);
@@ -202,7 +217,70 @@
* Returns the title or empty string
*/
private String getTitle() {
- return Utilities.trim(getString(titleIndex));
+ return Utilities.trim(getString(mTitleIndex));
+ }
+
+ /**
+ * When loading an app widget for the workspace, returns it's app widget id
+ */
+ public int getAppWidgetId() {
+ return getInt(mAppWidgetIdIndex);
+ }
+
+ /**
+ * When loading an app widget for the workspace, returns the widget provider
+ */
+ public String getAppWidgetProvider() {
+ return getString(mAppWidgetProviderIndex);
+ }
+
+ /**
+ * Returns the x position for the item in the cell layout's grid
+ */
+ public int getSpanX() {
+ return getInt(mSpanXIndex);
+ }
+
+ /**
+ * Returns the y position for the item in the cell layout's grid
+ */
+ public int getSpanY() {
+ return getInt(mSpanYIndex);
+ }
+
+ /**
+ * Returns the rank for the item
+ */
+ public int getRank() {
+ return getInt(mRankIndex);
+ }
+
+ /**
+ * Returns the options for the item
+ */
+ public int getOptions() {
+ return getInt(mOptionsIndex);
+ }
+
+ /**
+ * When loading an app widget for the workspace, returns it's app widget source
+ */
+ public int getAppWidgetSource() {
+ return getInt(mAppWidgetSourceIndex);
+ }
+
+ /**
+ * Returns the screen that the item is on
+ */
+ public int getScreen() {
+ return getInt(mScreenIndex);
+ }
+
+ /**
+ * Returns the UX container that the item is in
+ */
+ public int getContainer() {
+ return getInt(mContainerIndex);
}
/**
@@ -320,7 +398,7 @@
*/
public void markDeleted(String reason) {
FileLog.e(TAG, reason);
- itemsToRemove.add(id);
+ mItemsToRemove.add(id);
}
/**
@@ -328,10 +406,10 @@
* @return true is any item was removed.
*/
public boolean commitDeleted() {
- if (itemsToRemove.size() > 0) {
+ if (mItemsToRemove.size() > 0) {
// Remove dead items
mContext.getContentResolver().delete(mContentUri, Utilities.createDbSelectionQuery(
- LauncherSettings.Favorites._ID, itemsToRemove), null);
+ Favorites._ID, mItemsToRemove), null);
return true;
}
return false;
@@ -342,7 +420,7 @@
*/
public void markRestored() {
if (restoreFlag != 0) {
- restoredRows.add(id);
+ mRestoredRows.add(id);
restoreFlag = 0;
}
}
@@ -352,13 +430,13 @@
}
public void commitRestoredItems() {
- if (restoredRows.size() > 0) {
+ if (mRestoredRows.size() > 0) {
// Update restored items that no longer require special handling
ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites.RESTORED, 0);
+ values.put(Favorites.RESTORED, 0);
mContext.getContentResolver().update(mContentUri, values,
Utilities.createDbSelectionQuery(
- LauncherSettings.Favorites._ID, restoredRows), null);
+ Favorites._ID, mRestoredRows), null);
}
}
@@ -366,8 +444,7 @@
* Returns true is the item is on workspace or hotseat
*/
public boolean isOnWorkspaceOrHotseat() {
- return container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
- container == LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+ return container == Favorites.CONTAINER_DESKTOP || container == Favorites.CONTAINER_HOTSEAT;
}
/**
@@ -381,9 +458,9 @@
public void applyCommonProperties(ItemInfo info) {
info.id = id;
info.container = container;
- info.screenId = getInt(screenIndex);
- info.cellX = getInt(cellXIndex);
- info.cellY = getInt(cellYIndex);
+ info.screenId = getInt(mScreenIndex);
+ info.cellX = getInt(mCellXIndex);
+ info.cellY = getInt(mCellYIndex);
}
public void checkAndAddItem(ItemInfo info, BgDataModel dataModel) {
@@ -396,7 +473,7 @@
*/
public void checkAndAddItem(
ItemInfo info, BgDataModel dataModel, LoaderMemoryLogger logger) {
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ if (info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
// Ensure that it is a valid intent. An exception here will
// cause the item loading to get skipped
ShortcutKey.fromItemInfo(info);
@@ -413,9 +490,9 @@
*/
protected boolean checkItemPlacement(ItemInfo item) {
int containerIndex = item.screenId;
- if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ if (item.container == Favorites.CONTAINER_HOTSEAT) {
final GridOccupancy hotseatOccupancy =
- occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT);
+ mOccupied.get(Favorites.CONTAINER_HOTSEAT);
if (item.screenId >= mIDP.numDatabaseHotseatIcons) {
Log.e(TAG, "Error loading shortcut " + item
@@ -438,19 +515,18 @@
} else {
final GridOccupancy occupancy = new GridOccupancy(mIDP.numDatabaseHotseatIcons, 1);
occupancy.cells[item.screenId][0] = true;
- occupied.put(LauncherSettings.Favorites.CONTAINER_HOTSEAT, occupancy);
+ mOccupied.put(Favorites.CONTAINER_HOTSEAT, occupancy);
return true;
}
- } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ } else if (item.container != Favorites.CONTAINER_DESKTOP) {
// Skip further checking if it is not the hotseat or workspace container
return true;
}
final int countX = mIDP.numColumns;
final int countY = mIDP.numRows;
- if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- item.cellX < 0 || item.cellY < 0 ||
- item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
+ if (item.container == Favorites.CONTAINER_DESKTOP && item.cellX < 0 || item.cellY < 0
+ || item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
Log.e(TAG, "Error loading shortcut " + item
+ " into cell (" + containerIndex + "-" + item.screenId + ":"
+ item.cellX + "," + item.cellY
@@ -458,7 +534,7 @@
return false;
}
- if (!occupied.containsKey(item.screenId)) {
+ if (!mOccupied.containsKey(item.screenId)) {
GridOccupancy screen = new GridOccupancy(countX + 1, countY + 1);
if (item.screenId == Workspace.FIRST_SCREEN_ID && FeatureFlags.QSB_ON_FIRST_SCREEN) {
// Mark the first X columns (X is width of the search container) in the first row as
@@ -468,9 +544,9 @@
int spanY = 1;
screen.markCells(0, 0, spanX, spanY, true);
}
- occupied.put(item.screenId, screen);
+ mOccupied.put(item.screenId, screen);
}
- final GridOccupancy occupancy = occupied.get(item.screenId);
+ final GridOccupancy occupancy = mOccupied.get(item.screenId);
// Check if any workspace icons overlap with each other
if (occupancy.isRegionVacant(item.cellX, item.cellY, item.spanX, item.spanY)) {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 46a6a66..da9be49 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -58,7 +58,8 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
-import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.LauncherSettings.Settings;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
@@ -198,7 +199,7 @@
}
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
- TimingLogger logger = new TimingLogger(TAG, "run");
+ TimingLogger timingLogger = new TimingLogger(TAG, "run");
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
@@ -208,7 +209,7 @@
} finally {
Trace.endSection();
}
- logASplit(logger, "loadWorkspace");
+ logASplit(timingLogger, "loadWorkspace");
// 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
@@ -216,22 +217,23 @@
// (e.g. both grid preview and minimal device mode uses a different db)
if (mApp.getInvariantDeviceProfile().dbFile.equals(mDbName)) {
verifyNotStopped();
- sanitizeData();
- logASplit(logger, "sanitizeData");
+ sanitizeFolders(mItemsDeleted);
+ sanitizeWidgetsShortcutsAndPackages();
+ logASplit(timingLogger, "sanitizeData");
}
verifyNotStopped();
mLauncherBinder.bindWorkspace(true /* incrementBindId */);
- logASplit(logger, "bindWorkspace");
+ logASplit(timingLogger, "bindWorkspace");
mModelDelegate.workspaceLoadComplete();
// Notify the installer packages of packages with active installs on the first screen.
sendFirstScreenActiveInstallsBroadcast();
- logASplit(logger, "sendFirstScreenActiveInstallsBroadcast");
+ logASplit(timingLogger, "sendFirstScreenActiveInstallsBroadcast");
// Take a break
waitForIdle();
- logASplit(logger, "step 1 complete");
+ logASplit(timingLogger, "step 1 complete");
verifyNotStopped();
// second step
@@ -242,11 +244,11 @@
} finally {
Trace.endSection();
}
- logASplit(logger, "loadAllApps");
+ logASplit(timingLogger, "loadAllApps");
verifyNotStopped();
mLauncherBinder.bindAllApps();
- logASplit(logger, "bindAllApps");
+ logASplit(timingLogger, "bindAllApps");
verifyNotStopped();
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
@@ -254,69 +256,69 @@
updateHandler.updateIcons(allActivityList,
LauncherActivityCachingLogic.newInstance(mApp.getContext()),
mApp.getModel()::onPackageIconsUpdated);
- logASplit(logger, "update icon cache");
+ logASplit(timingLogger, "update icon cache");
verifyNotStopped();
- logASplit(logger, "save shortcuts in icon cache");
+ logASplit(timingLogger, "save shortcuts in icon cache");
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
mApp.getModel()::onPackageIconsUpdated);
// Take a break
waitForIdle();
- logASplit(logger, "step 2 complete");
+ logASplit(timingLogger, "step 2 complete");
verifyNotStopped();
// third step
List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
- logASplit(logger, "loadDeepShortcuts");
+ logASplit(timingLogger, "loadDeepShortcuts");
verifyNotStopped();
mLauncherBinder.bindDeepShortcuts();
- logASplit(logger, "bindDeepShortcuts");
+ logASplit(timingLogger, "bindDeepShortcuts");
verifyNotStopped();
- logASplit(logger, "save deep shortcuts in icon cache");
+ logASplit(timingLogger, "save deep shortcuts in icon cache");
updateHandler.updateIcons(allDeepShortcuts,
new ShortcutCachingLogic(), (pkgs, user) -> { });
// Take a break
waitForIdle();
- logASplit(logger, "step 3 complete");
+ logASplit(timingLogger, "step 3 complete");
verifyNotStopped();
// fourth step
List<ComponentWithLabelAndIcon> allWidgetsList =
mBgDataModel.widgetsModel.update(mApp, null);
- logASplit(logger, "load widgets");
+ logASplit(timingLogger, "load widgets");
verifyNotStopped();
mLauncherBinder.bindWidgets();
- logASplit(logger, "bindWidgets");
+ logASplit(timingLogger, "bindWidgets");
verifyNotStopped();
updateHandler.updateIcons(allWidgetsList,
new ComponentWithIconCachingLogic(mApp.getContext(), true),
mApp.getModel()::onWidgetLabelsUpdated);
- logASplit(logger, "save widgets in icon cache");
+ logASplit(timingLogger, "save widgets in icon cache");
// fifth step
loadFolderNames();
verifyNotStopped();
updateHandler.finish();
- logASplit(logger, "finish icon update");
+ logASplit(timingLogger, "finish icon update");
mModelDelegate.modelLoadComplete();
transaction.commit();
memoryLogger.clearLogs();
} catch (CancellationException e) {
// Loader stopped, ignore
- logASplit(logger, "Cancelled");
+ logASplit(timingLogger, "Cancelled");
} catch (Exception e) {
memoryLogger.printLogs();
throw e;
} finally {
- logger.dumpToLog();
+ timingLogger.dumpToLog();
}
TraceHelper.INSTANCE.endSection(traceToken);
}
@@ -326,9 +328,10 @@
this.notify();
}
- private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, LoaderMemoryLogger logger) {
- loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI,
- null /* selection */, logger);
+ private void loadWorkspace(
+ List<ShortcutInfo> allDeepShortcuts, LoaderMemoryLogger memoryLogger) {
+ loadWorkspace(allDeepShortcuts, Favorites.CONTENT_URI,
+ null /* selection */, memoryLogger);
}
protected void loadWorkspace(
@@ -340,7 +343,7 @@
List<ShortcutInfo> allDeepShortcuts,
Uri contentUri,
String selection,
- @Nullable LoaderMemoryLogger logger) {
+ @Nullable LoaderMemoryLogger memoryLogger) {
final Context context = mApp.getContext();
final ContentResolver contentResolver = context.getContentResolver();
final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
@@ -356,13 +359,11 @@
if (clearDb) {
Log.d(TAG, "loadWorkspace: resetting launcher database");
- LauncherSettings.Settings.call(contentResolver,
- LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
+ Settings.call(contentResolver, Settings.METHOD_CREATE_EMPTY_DB);
}
Log.d(TAG, "loadWorkspace: loading default favorites");
- LauncherSettings.Settings.call(contentResolver,
- LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES);
+ Settings.call(contentResolver, Settings.METHOD_LOAD_DEFAULT_FAVORITES);
synchronized (mBgDataModel) {
mBgDataModel.clear();
@@ -380,24 +381,8 @@
contentResolver.query(contentUri, null, selection, null, null), contentUri,
mApp, mUserManagerState);
final Bundle extras = c.getExtras();
- mDbName = extras == null
- ? null : extras.getString(LauncherSettings.Settings.EXTRA_DB_NAME);
+ mDbName = extras == null ? null : extras.getString(Settings.EXTRA_DB_NAME);
try {
- final int appWidgetIdIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.APPWIDGET_ID);
- final int appWidgetProviderIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.APPWIDGET_PROVIDER);
- final int spanXIndex = c.getColumnIndexOrThrow
- (LauncherSettings.Favorites.SPANX);
- final int spanYIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.SPANY);
- final int rankIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.RANK);
- final int optionsIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.OPTIONS);
- final int sourceContainerIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.APPWIDGET_SOURCE);
-
final LongSparseArray<Boolean> unlockedUsers = new LongSparseArray<>();
mUserManagerState.init(mUserCache, mUserManager);
@@ -425,437 +410,23 @@
unlockedUsers.put(serialNo, userUnlocked);
}
- WorkspaceItemInfo info;
- LauncherAppWidgetInfo appWidgetInfo;
- LauncherAppWidgetProviderInfo widgetProviderInfo;
- Intent intent;
- String targetPkg;
List<IconRequestInfo<WorkspaceItemInfo>> iconRequestInfos = new ArrayList<>();
while (!mStopped && c.moveToNext()) {
- try {
- if (c.user == null) {
- // User has been deleted, remove the item.
- c.markDeleted("User has been deleted");
- continue;
- }
-
- boolean allowMissingTarget = false;
- switch (c.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
- intent = c.parseIntent();
- if (intent == null) {
- c.markDeleted("Invalid or null intent");
- continue;
- }
-
- int disabledState = mUserManagerState.isUserQuiet(c.serialNumber)
- ? WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER : 0;
- ComponentName cn = intent.getComponent();
- targetPkg = cn == null ? intent.getPackage() : cn.getPackageName();
-
- if (TextUtils.isEmpty(targetPkg) &&
- c.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
- c.markDeleted("Only legacy shortcuts can have null package");
- continue;
- }
-
- // If there is no target package, its an implicit intent
- // (legacy shortcut) which is always valid
- boolean validTarget = TextUtils.isEmpty(targetPkg) ||
- mLauncherApps.isPackageEnabled(targetPkg, c.user);
-
- // If it's a deep shortcut, we'll use pinned shortcuts to restore it
- if (cn != null && validTarget && c.itemType
- != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- // If the apk is present and the shortcut points to a specific
- // component.
-
- // If the component is already present
- if (mLauncherApps.isActivityEnabled(cn, c.user)) {
- // no special handling necessary for this item
- c.markRestored();
- } else {
- // Gracefully try to find a fallback activity.
- intent = pmHelper.getAppLaunchIntent(targetPkg, c.user);
- if (intent != null) {
- c.restoreFlag = 0;
- c.updater().put(
- LauncherSettings.Favorites.INTENT,
- intent.toUri(0)).commit();
- cn = intent.getComponent();
- } else {
- c.markDeleted("Unable to find a launch target");
- continue;
- }
- }
- }
- // else if cn == null => can't infer much, leave it
- // else if !validPkg => could be restored icon or missing sd-card
-
- if (!TextUtils.isEmpty(targetPkg) && !validTarget) {
- // Points to a valid app (superset of cn != null) but the apk
- // is not available.
-
- if (c.restoreFlag != 0) {
- // Package is not yet available but might be
- // installed later.
- FileLog.d(TAG, "package not yet restored: " + targetPkg);
-
- tempPackageKey.update(targetPkg, c.user);
- if (c.hasRestoreFlag(WorkspaceItemInfo.FLAG_RESTORE_STARTED)) {
- // Restore has started once.
- } else if (installingPkgs.containsKey(tempPackageKey)) {
- // App restore has started. Update the flag
- c.restoreFlag |= WorkspaceItemInfo.FLAG_RESTORE_STARTED;
- c.updater().put(LauncherSettings.Favorites.RESTORED,
- c.restoreFlag).commit();
- } else {
- c.markDeleted("Unrestored app removed: " + targetPkg);
- continue;
- }
- } else if (pmHelper.isAppOnSdcard(targetPkg, c.user)) {
- // Package is present but not available.
- disabledState |= WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE;
- // Add the icon on the workspace anyway.
- allowMissingTarget = true;
- } else if (!isSdCardReady) {
- // SdCard is not ready yet. Package might get available,
- // once it is ready.
- Log.d(TAG, "Missing pkg, will check later: " + targetPkg);
- mPendingPackages.add(new PackageUserKey(targetPkg, c.user));
- // Add the icon on the workspace anyway.
- allowMissingTarget = true;
- } else {
- // Do not wait for external media load anymore.
- c.markDeleted("Invalid package removed: " + targetPkg);
- continue;
- }
- }
-
- if ((c.restoreFlag & WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI) != 0) {
- validTarget = false;
- }
-
- if (validTarget) {
- // The shortcut points to a valid target (either no target
- // or something which is ready to be used)
- c.markRestored();
- }
-
- boolean useLowResIcon = !c.isOnWorkspaceOrHotseat();
-
- if (c.restoreFlag != 0) {
- // Already verified above that user is same as default user
- info = c.getRestoredItemInfo(intent);
- } else if (c.itemType ==
- LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- info = c.getAppShortcutInfo(
- intent,
- allowMissingTarget,
- useLowResIcon,
- !FeatureFlags.ENABLE_BULK_WORKSPACE_ICON_LOADING.get());
- } else if (c.itemType ==
- LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
-
- ShortcutKey key = ShortcutKey.fromIntent(intent, c.user);
- if (unlockedUsers.get(c.serialNumber)) {
- ShortcutInfo pinnedShortcut =
- shortcutKeyToPinnedShortcuts.get(key);
- if (pinnedShortcut == null) {
- // The shortcut is no longer valid.
- c.markDeleted("Pinned shortcut not found");
- continue;
- }
- info = new WorkspaceItemInfo(pinnedShortcut, context);
- // If the pinned deep shortcut is no longer published,
- // use the last saved icon instead of the default.
- mIconCache.getShortcutIcon(info, pinnedShortcut, c::loadIcon);
-
- if (pmHelper.isAppSuspended(
- pinnedShortcut.getPackage(), info.user)) {
- info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
- }
- intent = info.getIntent();
- allDeepShortcuts.add(pinnedShortcut);
- } else {
- // Create a shortcut info in disabled mode for now.
- info = c.loadSimpleWorkspaceItem();
- info.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
- }
- } else { // item type == ITEM_TYPE_SHORTCUT
- info = c.loadSimpleWorkspaceItem();
-
- // Shortcuts are only available on the primary profile
- if (!TextUtils.isEmpty(targetPkg)
- && pmHelper.isAppSuspended(targetPkg, c.user)) {
- disabledState |= FLAG_DISABLED_SUSPENDED;
- }
- info.options = c.getInt(optionsIndex);
-
- // App shortcuts that used to be automatically added to Launcher
- // didn't always have the correct intent flags set, so do that
- // here
- if (intent.getAction() != null &&
- intent.getCategories() != null &&
- intent.getAction().equals(Intent.ACTION_MAIN) &&
- intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
- intent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- }
- }
-
- if (info != null) {
- if (info.itemType
- != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- // Skip deep shortcuts; their title and icons have already been
- // loaded above.
- iconRequestInfos.add(
- c.createIconRequestInfo(info, useLowResIcon));
- }
-
- c.applyCommonProperties(info);
-
- info.intent = intent;
- info.rank = c.getInt(rankIndex);
- info.spanX = 1;
- info.spanY = 1;
- info.runtimeStatusFlags |= disabledState;
- if (isSafeMode && !isSystemApp(context, intent)) {
- info.runtimeStatusFlags |= FLAG_DISABLED_SAFEMODE;
- }
- LauncherActivityInfo activityInfo = c.getLauncherActivityInfo();
- if (activityInfo != null) {
- info.setProgressLevel(
- PackageManagerHelper
- .getLoadingProgress(activityInfo),
- PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
- }
-
- if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) {
- tempPackageKey.update(targetPkg, c.user);
- SessionInfo si = installingPkgs.get(tempPackageKey);
- if (si == null) {
- info.runtimeStatusFlags &=
- ~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
- } else if (activityInfo == null) {
- int installProgress = (int) (si.getProgress() * 100);
-
- info.setProgressLevel(
- installProgress,
- PackageInstallInfo.STATUS_INSTALLING);
- }
- }
-
- c.checkAndAddItem(info, mBgDataModel, logger);
- } else {
- throw new RuntimeException("Unexpected null WorkspaceItemInfo");
- }
- break;
-
- case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
- FolderInfo folderInfo = mBgDataModel.findOrMakeFolder(c.id);
- c.applyCommonProperties(folderInfo);
-
- // Do not trim the folder label, as is was set by the user.
- folderInfo.title = c.getString(c.titleIndex);
- folderInfo.spanX = 1;
- folderInfo.spanY = 1;
- folderInfo.options = c.getInt(optionsIndex);
-
- // no special handling required for restored folders
- c.markRestored();
-
- c.checkAndAddItem(folderInfo, mBgDataModel, logger);
- break;
-
- case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
- if (WidgetsModel.GO_DISABLE_WIDGETS) {
- c.markDeleted("Only legacy shortcuts can have null package");
- continue;
- }
- // Follow through
- case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
- // Read all Launcher-specific widget details
- boolean customWidget = c.itemType ==
- LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
-
- int appWidgetId = c.getInt(appWidgetIdIndex);
- String savedProvider = c.getString(appWidgetProviderIndex);
- final ComponentName component;
-
- boolean isSearchWidget = (c.getInt(optionsIndex)
- & LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET) != 0;
- if (isSearchWidget) {
- component = QsbContainerView.getSearchComponentName(context);
- if (component == null) {
- c.markDeleted("Discarding SearchWidget without packagename ");
- continue;
- }
- } else {
- component = ComponentName.unflattenFromString(savedProvider);
- }
- final boolean isIdValid = !c.hasRestoreFlag(
- LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
- final boolean wasProviderReady = !c.hasRestoreFlag(
- LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY);
-
- ComponentKey providerKey = new ComponentKey(component, c.user);
- if (!mWidgetProvidersMap.containsKey(providerKey)) {
- mWidgetProvidersMap.put(providerKey,
- widgetHelper.findProvider(component, c.user));
- }
- final AppWidgetProviderInfo provider =
- mWidgetProvidersMap.get(providerKey);
-
- final boolean isProviderReady = isValidProvider(provider);
- if (!isSafeMode && !customWidget &&
- wasProviderReady && !isProviderReady) {
- c.markDeleted(
- "Deleting widget that isn't installed anymore: "
- + provider);
- } else {
- if (isProviderReady) {
- appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
- provider.provider);
-
- // The provider is available. So the widget is either
- // available or not available. We do not need to track
- // any future restore updates.
- int status = c.restoreFlag &
- ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED &
- ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
- if (!wasProviderReady) {
- // If provider was not previously ready, update the
- // status and UI flag.
-
- // Id would be valid only if the widget restore broadcast was received.
- if (isIdValid) {
- status |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
- }
- }
- appWidgetInfo.restoreStatus = status;
- } else {
- Log.v(TAG, "Widget restore pending id=" + c.id
- + " appWidgetId=" + appWidgetId
- + " status =" + c.restoreFlag);
- appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
- component);
- appWidgetInfo.restoreStatus = c.restoreFlag;
-
- tempPackageKey.update(component.getPackageName(), c.user);
- SessionInfo si =
- installingPkgs.get(tempPackageKey);
- Integer installProgress = si == null
- ? null
- : (int) (si.getProgress() * 100);
-
- if (c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED)) {
- // Restore has started once.
- } else if (installProgress != null) {
- // App restore has started. Update the flag
- appWidgetInfo.restoreStatus |=
- LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
- } else if (!isSafeMode) {
- c.markDeleted("Unrestored widget removed: " + component);
- continue;
- }
-
- appWidgetInfo.installProgress =
- installProgress == null ? 0 : installProgress;
- }
- if (appWidgetInfo.hasRestoreFlag(
- LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)) {
- appWidgetInfo.bindOptions = c.parseIntent();
- }
-
- c.applyCommonProperties(appWidgetInfo);
- appWidgetInfo.spanX = c.getInt(spanXIndex);
- appWidgetInfo.spanY = c.getInt(spanYIndex);
- appWidgetInfo.options = c.getInt(optionsIndex);
- appWidgetInfo.user = c.user;
- appWidgetInfo.sourceContainer = c.getInt(sourceContainerIndex);
-
- if (appWidgetInfo.spanX <= 0 || appWidgetInfo.spanY <= 0) {
- c.markDeleted("Widget has invalid size: "
- + appWidgetInfo.spanX + "x" + appWidgetInfo.spanY);
- continue;
- }
- widgetProviderInfo =
- widgetHelper.getLauncherAppWidgetInfo(appWidgetId);
- if (widgetProviderInfo != null
- && (appWidgetInfo.spanX < widgetProviderInfo.minSpanX
- || appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) {
- FileLog.d(TAG, "Widget " + widgetProviderInfo.getComponent()
- + " minSizes not meet: span=" + appWidgetInfo.spanX
- + "x" + appWidgetInfo.spanY + " minSpan="
- + widgetProviderInfo.minSpanX + "x"
- + widgetProviderInfo.minSpanY);
- logWidgetInfo(mApp.getInvariantDeviceProfile(),
- widgetProviderInfo);
- }
- if (!c.isOnWorkspaceOrHotseat()) {
- c.markDeleted("Widget found where container != " +
- "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
- continue;
- }
-
- if (!customWidget) {
- String providerName =
- appWidgetInfo.providerName.flattenToString();
- if (!providerName.equals(savedProvider) ||
- (appWidgetInfo.restoreStatus != c.restoreFlag)) {
- c.updater()
- .put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,
- providerName)
- .put(LauncherSettings.Favorites.RESTORED,
- appWidgetInfo.restoreStatus)
- .commit();
- }
- }
-
- if (appWidgetInfo.restoreStatus !=
- LauncherAppWidgetInfo.RESTORE_COMPLETED) {
- appWidgetInfo.pendingItemInfo = WidgetsModel.newPendingItemInfo(
- mApp.getContext(),
- appWidgetInfo.providerName,
- appWidgetInfo.user);
- mIconCache.getTitleAndIconForApp(
- appWidgetInfo.pendingItemInfo, false);
- }
-
- c.checkAndAddItem(appWidgetInfo, mBgDataModel);
- }
- break;
- }
- } catch (Exception e) {
- Log.e(TAG, "Desktop items loading interrupted", e);
- }
+ processWorkspaceItem(c, memoryLogger, installingPkgs, isSdCardReady,
+ tempPackageKey, widgetHelper, pmHelper, shortcutKeyToPinnedShortcuts,
+ iconRequestInfos, unlockedUsers, isSafeMode, allDeepShortcuts);
}
- if (FeatureFlags.ENABLE_BULK_WORKSPACE_ICON_LOADING.get()) {
- Trace.beginSection("LoadWorkspaceIconsInBulk");
- try {
- mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
- for (IconRequestInfo<WorkspaceItemInfo> iconRequestInfo :
- iconRequestInfos) {
- WorkspaceItemInfo wai = iconRequestInfo.itemInfo;
- if (mIconCache.isDefaultIcon(wai.bitmap, wai.user)) {
- iconRequestInfo.loadWorkspaceIcon(mApp.getContext());
- }
- }
- } finally {
- Trace.endSection();
- }
- }
+ maybeLoadWorkspaceIconsInBulk(iconRequestInfos);
} finally {
IOUtils.closeSilently(c);
}
// Load delegate items
- mModelDelegate.loadItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
+ mModelDelegate.loadHotseatItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
+ mModelDelegate.loadAllAppsItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
+ mModelDelegate.loadWidgetsRecommendationItems();
+ mModelDelegate.markActive();
// Load string cache
mModelDelegate.loadStringCache(mBgDataModel.stringCache);
@@ -885,7 +456,7 @@
info.rank = rank;
if (info.usingLowResIcon()
- && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+ && info.itemType == Favorites.ITEM_TYPE_APPLICATION
&& verifier.isItemInPreview(info.rank)) {
mIconCache.getTitleAndIcon(info, false);
}
@@ -896,6 +467,418 @@
}
}
+ private void processWorkspaceItem(LoaderCursor c,
+ LoaderMemoryLogger memoryLogger,
+ HashMap<PackageUserKey, SessionInfo> installingPkgs,
+ boolean isSdCardReady,
+ PackageUserKey tempPackageKey,
+ WidgetManagerHelper widgetHelper,
+ PackageManagerHelper pmHelper,
+ Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts,
+ List<IconRequestInfo<WorkspaceItemInfo>> iconRequestInfos,
+ LongSparseArray<Boolean> unlockedUsers,
+ boolean isSafeMode,
+ List<ShortcutInfo> allDeepShortcuts) {
+
+ try {
+ if (c.user == null) {
+ // User has been deleted, remove the item.
+ c.markDeleted("User has been deleted");
+ return;
+ }
+
+ boolean allowMissingTarget = false;
+ switch (c.itemType) {
+ case Favorites.ITEM_TYPE_SHORTCUT:
+ case Favorites.ITEM_TYPE_APPLICATION:
+ case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+ Intent intent = c.parseIntent();
+ if (intent == null) {
+ c.markDeleted("Invalid or null intent");
+ return;
+ }
+
+ int disabledState = mUserManagerState.isUserQuiet(c.serialNumber)
+ ? WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER : 0;
+ ComponentName cn = intent.getComponent();
+ String targetPkg = cn == null ? intent.getPackage() : cn.getPackageName();
+
+ if (TextUtils.isEmpty(targetPkg)
+ && c.itemType != Favorites.ITEM_TYPE_SHORTCUT) {
+ c.markDeleted("Only legacy shortcuts can have null package");
+ return;
+ }
+
+ // If there is no target package, it's an implicit intent
+ // (legacy shortcut) which is always valid
+ boolean validTarget = TextUtils.isEmpty(targetPkg)
+ || mLauncherApps.isPackageEnabled(targetPkg, c.user);
+
+ // If it's a deep shortcut, we'll use pinned shortcuts to restore it
+ if (cn != null && validTarget && c.itemType
+ != Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ // If the apk is present and the shortcut points to a specific component.
+
+ // If the component is already present
+ if (mLauncherApps.isActivityEnabled(cn, c.user)) {
+ // no special handling necessary for this item
+ c.markRestored();
+ } else {
+ // Gracefully try to find a fallback activity.
+ intent = pmHelper.getAppLaunchIntent(targetPkg, c.user);
+ if (intent != null) {
+ c.restoreFlag = 0;
+ c.updater().put(
+ Favorites.INTENT,
+ intent.toUri(0)).commit();
+ cn = intent.getComponent();
+ } else {
+ c.markDeleted("Unable to find a launch target");
+ return;
+ }
+ }
+ }
+ // else if cn == null => can't infer much, leave it
+ // else if !validPkg => could be restored icon or missing sd-card
+
+ if (!TextUtils.isEmpty(targetPkg) && !validTarget) {
+ // Points to a valid app (superset of cn != null) but the apk
+ // is not available.
+
+ if (c.restoreFlag != 0) {
+ // Package is not yet available but might be
+ // installed later.
+ FileLog.d(TAG, "package not yet restored: " + targetPkg);
+
+ tempPackageKey.update(targetPkg, c.user);
+ if (c.hasRestoreFlag(WorkspaceItemInfo.FLAG_RESTORE_STARTED)) {
+ // Restore has started once.
+ } else if (installingPkgs.containsKey(tempPackageKey)) {
+ // App restore has started. Update the flag
+ c.restoreFlag |= WorkspaceItemInfo.FLAG_RESTORE_STARTED;
+ c.updater().put(Favorites.RESTORED,
+ c.restoreFlag).commit();
+ } else {
+ c.markDeleted("Unrestored app removed: " + targetPkg);
+ return;
+ }
+ } else if (pmHelper.isAppOnSdcard(targetPkg, c.user)) {
+ // Package is present but not available.
+ disabledState |= WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE;
+ // Add the icon on the workspace anyway.
+ allowMissingTarget = true;
+ } else if (!isSdCardReady) {
+ // SdCard is not ready yet. Package might get available,
+ // once it is ready.
+ Log.d(TAG, "Missing pkg, will check later: " + targetPkg);
+ mPendingPackages.add(new PackageUserKey(targetPkg, c.user));
+ // Add the icon on the workspace anyway.
+ allowMissingTarget = true;
+ } else {
+ // Do not wait for external media load anymore.
+ c.markDeleted("Invalid package removed: " + targetPkg);
+ return;
+ }
+ }
+
+ if ((c.restoreFlag & WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI) != 0) {
+ validTarget = false;
+ }
+
+ if (validTarget) {
+ // The shortcut points to a valid target (either no target
+ // or something which is ready to be used)
+ c.markRestored();
+ }
+
+ boolean useLowResIcon = !c.isOnWorkspaceOrHotseat();
+
+ WorkspaceItemInfo info;
+ if (c.restoreFlag != 0) {
+ // Already verified above that user is same as default user
+ info = c.getRestoredItemInfo(intent);
+ } else if (c.itemType == Favorites.ITEM_TYPE_APPLICATION) {
+ info = c.getAppShortcutInfo(intent, allowMissingTarget, useLowResIcon,
+ !FeatureFlags.ENABLE_BULK_WORKSPACE_ICON_LOADING.get());
+ } else if (c.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ ShortcutKey key = ShortcutKey.fromIntent(intent, c.user);
+ if (unlockedUsers.get(c.serialNumber)) {
+ ShortcutInfo pinnedShortcut = shortcutKeyToPinnedShortcuts.get(key);
+ if (pinnedShortcut == null) {
+ // The shortcut is no longer valid.
+ c.markDeleted("Pinned shortcut not found");
+ return;
+ }
+ info = new WorkspaceItemInfo(pinnedShortcut, mApp.getContext());
+ // If the pinned deep shortcut is no longer published,
+ // use the last saved icon instead of the default.
+ mIconCache.getShortcutIcon(info, pinnedShortcut, c::loadIcon);
+
+ if (pmHelper.isAppSuspended(
+ pinnedShortcut.getPackage(), info.user)) {
+ info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
+ }
+ intent = info.getIntent();
+ allDeepShortcuts.add(pinnedShortcut);
+ } else {
+ // Create a shortcut info in disabled mode for now.
+ info = c.loadSimpleWorkspaceItem();
+ info.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
+ }
+ } else { // item type == ITEM_TYPE_SHORTCUT
+ info = c.loadSimpleWorkspaceItem();
+
+ // Shortcuts are only available on the primary profile
+ if (!TextUtils.isEmpty(targetPkg)
+ && pmHelper.isAppSuspended(targetPkg, c.user)) {
+ disabledState |= FLAG_DISABLED_SUSPENDED;
+ }
+ info.options = c.getOptions();
+
+ // App shortcuts that used to be automatically added to Launcher
+ // didn't always have the correct intent flags set, so do that here
+ if (intent.getAction() != null
+ && intent.getCategories() != null
+ && intent.getAction().equals(Intent.ACTION_MAIN)
+ && intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ }
+ }
+
+ if (info != null) {
+ if (info.itemType != Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ // Skip deep shortcuts; their title and icons have already been
+ // loaded above.
+ iconRequestInfos.add(c.createIconRequestInfo(info, useLowResIcon));
+ }
+
+ c.applyCommonProperties(info);
+
+ info.intent = intent;
+ info.rank = c.getRank();
+ info.spanX = 1;
+ info.spanY = 1;
+ info.runtimeStatusFlags |= disabledState;
+ if (isSafeMode && !isSystemApp(mApp.getContext(), intent)) {
+ info.runtimeStatusFlags |= FLAG_DISABLED_SAFEMODE;
+ }
+ LauncherActivityInfo activityInfo = c.getLauncherActivityInfo();
+ if (activityInfo != null) {
+ info.setProgressLevel(
+ PackageManagerHelper.getLoadingProgress(activityInfo),
+ PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
+ }
+
+ if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) {
+ tempPackageKey.update(targetPkg, c.user);
+ SessionInfo si = installingPkgs.get(tempPackageKey);
+ if (si == null) {
+ info.runtimeStatusFlags
+ &= ~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
+ } else if (activityInfo == null) {
+ int installProgress = (int) (si.getProgress() * 100);
+
+ info.setProgressLevel(installProgress,
+ PackageInstallInfo.STATUS_INSTALLING);
+ }
+ }
+
+ c.checkAndAddItem(info, mBgDataModel, memoryLogger);
+ } else {
+ throw new RuntimeException("Unexpected null WorkspaceItemInfo");
+ }
+ break;
+
+ case Favorites.ITEM_TYPE_FOLDER:
+ FolderInfo folderInfo = mBgDataModel.findOrMakeFolder(c.id);
+ c.applyCommonProperties(folderInfo);
+
+ // Do not trim the folder label, as is was set by the user.
+ folderInfo.title = c.getString(c.mTitleIndex);
+ folderInfo.spanX = 1;
+ folderInfo.spanY = 1;
+ folderInfo.options = c.getOptions();
+
+ // no special handling required for restored folders
+ c.markRestored();
+
+ c.checkAndAddItem(folderInfo, mBgDataModel, memoryLogger);
+ break;
+
+ case Favorites.ITEM_TYPE_APPWIDGET:
+ if (WidgetsModel.GO_DISABLE_WIDGETS) {
+ c.markDeleted("Only legacy shortcuts can have null package");
+ return;
+ }
+ // Follow through
+ case Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
+ // Read all Launcher-specific widget details
+ boolean customWidget = c.itemType
+ == Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
+
+ int appWidgetId = c.getAppWidgetId();
+ String savedProvider = c.getAppWidgetProvider();
+ final ComponentName component;
+
+ if ((c.getOptions() & LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET) != 0) {
+ component = QsbContainerView.getSearchComponentName(mApp.getContext());
+ if (component == null) {
+ c.markDeleted("Discarding SearchWidget without packagename ");
+ return;
+ }
+ } else {
+ component = ComponentName.unflattenFromString(savedProvider);
+ }
+ final boolean isIdValid =
+ !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
+ final boolean wasProviderReady =
+ !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY);
+
+ ComponentKey providerKey = new ComponentKey(component, c.user);
+ if (!mWidgetProvidersMap.containsKey(providerKey)) {
+ mWidgetProvidersMap.put(providerKey,
+ widgetHelper.findProvider(component, c.user));
+ }
+ final AppWidgetProviderInfo provider = mWidgetProvidersMap.get(providerKey);
+
+ final boolean isProviderReady = isValidProvider(provider);
+ if (!isSafeMode && !customWidget && wasProviderReady && !isProviderReady) {
+ c.markDeleted("Deleting widget that isn't installed anymore: " + provider);
+ } else {
+ LauncherAppWidgetInfo appWidgetInfo;
+ if (isProviderReady) {
+ appWidgetInfo =
+ new LauncherAppWidgetInfo(appWidgetId, provider.provider);
+
+ // The provider is available. So the widget is either
+ // available or not available. We do not need to track
+ // any future restore updates.
+ int status = c.restoreFlag
+ & ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED
+ & ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+ if (!wasProviderReady) {
+ // If provider was not previously ready, update status and UI flag.
+
+ // Id would be valid only if the widget restore broadcast received.
+ if (isIdValid) {
+ status |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
+ }
+ }
+ appWidgetInfo.restoreStatus = status;
+ } else {
+ Log.v(TAG, "Widget restore pending id=" + c.id
+ + " appWidgetId=" + appWidgetId
+ + " status =" + c.restoreFlag);
+ appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId, component);
+ appWidgetInfo.restoreStatus = c.restoreFlag;
+
+ tempPackageKey.update(component.getPackageName(), c.user);
+ SessionInfo si = installingPkgs.get(tempPackageKey);
+ Integer installProgress = si == null
+ ? null
+ : (int) (si.getProgress() * 100);
+
+ if (c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED)) {
+ // Restore has started once.
+ } else if (installProgress != null) {
+ // App restore has started. Update the flag
+ appWidgetInfo.restoreStatus
+ |= LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
+ } else if (!isSafeMode) {
+ c.markDeleted("Unrestored widget removed: " + component);
+ return;
+ }
+
+ appWidgetInfo.installProgress =
+ installProgress == null ? 0 : installProgress;
+ }
+ if (appWidgetInfo.hasRestoreFlag(
+ LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)) {
+ appWidgetInfo.bindOptions = c.parseIntent();
+ }
+
+ c.applyCommonProperties(appWidgetInfo);
+ appWidgetInfo.spanX = c.getSpanX();
+ appWidgetInfo.spanY = c.getSpanY();
+ appWidgetInfo.options = c.getOptions();
+ appWidgetInfo.user = c.user;
+ appWidgetInfo.sourceContainer = c.getAppWidgetSource();
+
+ if (appWidgetInfo.spanX <= 0 || appWidgetInfo.spanY <= 0) {
+ c.markDeleted("Widget has invalid size: "
+ + appWidgetInfo.spanX + "x" + appWidgetInfo.spanY);
+ return;
+ }
+ LauncherAppWidgetProviderInfo widgetProviderInfo =
+ widgetHelper.getLauncherAppWidgetInfo(appWidgetId);
+ if (widgetProviderInfo != null
+ && (appWidgetInfo.spanX < widgetProviderInfo.minSpanX
+ || appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) {
+ FileLog.d(TAG, "Widget " + widgetProviderInfo.getComponent()
+ + " minSizes not meet: span=" + appWidgetInfo.spanX
+ + "x" + appWidgetInfo.spanY + " minSpan="
+ + widgetProviderInfo.minSpanX + "x"
+ + widgetProviderInfo.minSpanY);
+ logWidgetInfo(mApp.getInvariantDeviceProfile(),
+ widgetProviderInfo);
+ }
+ if (!c.isOnWorkspaceOrHotseat()) {
+ c.markDeleted("Widget found where container != CONTAINER_DESKTOP"
+ + "nor CONTAINER_HOTSEAT - ignoring!");
+ return;
+ }
+
+ if (!customWidget) {
+ String providerName = appWidgetInfo.providerName.flattenToString();
+ if (!providerName.equals(savedProvider)
+ || (appWidgetInfo.restoreStatus != c.restoreFlag)) {
+ c.updater()
+ .put(Favorites.APPWIDGET_PROVIDER,
+ providerName)
+ .put(Favorites.RESTORED,
+ appWidgetInfo.restoreStatus)
+ .commit();
+ }
+ }
+
+ if (appWidgetInfo.restoreStatus
+ != LauncherAppWidgetInfo.RESTORE_COMPLETED) {
+ appWidgetInfo.pendingItemInfo = WidgetsModel.newPendingItemInfo(
+ mApp.getContext(),
+ appWidgetInfo.providerName,
+ appWidgetInfo.user);
+ mIconCache.getTitleAndIconForApp(
+ appWidgetInfo.pendingItemInfo, false);
+ }
+
+ c.checkAndAddItem(appWidgetInfo, mBgDataModel);
+ }
+ break;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Desktop items loading interrupted", e);
+ }
+ }
+
+ private void maybeLoadWorkspaceIconsInBulk(
+ List<IconRequestInfo<WorkspaceItemInfo>> iconRequestInfos) {
+ if (FeatureFlags.ENABLE_BULK_WORKSPACE_ICON_LOADING.get()) {
+ Trace.beginSection("LoadWorkspaceIconsInBulk");
+ try {
+ mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
+ for (IconRequestInfo<WorkspaceItemInfo> iconRequestInfo : iconRequestInfos) {
+ WorkspaceItemInfo wai = iconRequestInfo.itemInfo;
+ if (mIconCache.isDefaultIcon(wai.bitmap, wai.user)) {
+ iconRequestInfo.loadWorkspaceIcon(mApp.getContext());
+ }
+ }
+ } finally {
+ Trace.endSection();
+ }
+ }
+ }
+
private void setIgnorePackages(IconCacheUpdateHandler updateHandler) {
// Ignore packages which have a promise icon.
synchronized (mBgDataModel) {
@@ -917,15 +900,12 @@
}
}
- private void sanitizeData() {
- Context context = mApp.getContext();
- ContentResolver contentResolver = context.getContentResolver();
- if (mItemsDeleted) {
+ private void sanitizeFolders(boolean itemsDeleted) {
+ if (itemsDeleted) {
// Remove any empty folder
- int[] deletedFolderIds = LauncherSettings.Settings
- .call(contentResolver,
- LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS)
- .getIntArray(LauncherSettings.Settings.EXTRA_VALUE);
+ int[] deletedFolderIds = Settings.call(mApp.getContext().getContentResolver(),
+ Settings.METHOD_DELETE_EMPTY_FOLDERS)
+ .getIntArray(Settings.EXTRA_VALUE);
synchronized (mBgDataModel) {
for (int folderId : deletedFolderIds) {
mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId));
@@ -933,11 +913,16 @@
mBgDataModel.itemsIdMap.remove(folderId);
}
}
-
}
+ }
+
+ private void sanitizeWidgetsShortcutsAndPackages() {
+ Context context = mApp.getContext();
+ ContentResolver contentResolver = context.getContentResolver();
+
// Remove any ghost widgets
- LauncherSettings.Settings.call(contentResolver,
- LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS);
+ Settings.call(contentResolver,
+ Settings.METHOD_REMOVE_GHOST_WIDGETS);
// Update pinned state of model shortcuts
mBgDataModel.updateShortcutPinnedState(context);
@@ -1107,10 +1092,12 @@
FileLog.d(TAG, widgetDimension.toString());
}
- private static void logASplit(final TimingLogger logger, final String label) {
- logger.addSplit(label);
- if (DEBUG) {
- Log.d(TAG, label);
+ private static void logASplit(@Nullable TimingLogger timingLogger, String label) {
+ if (timingLogger != null) {
+ timingLogger.addSplit(label);
+ if (DEBUG) {
+ Log.d(TAG, label);
+ }
}
}
}
diff --git a/src/com/android/launcher3/model/ModelDelegate.java b/src/com/android/launcher3/model/ModelDelegate.java
index 3bd9470..0639a6c 100644
--- a/src/com/android/launcher3/model/ModelDelegate.java
+++ b/src/com/android/launcher3/model/ModelDelegate.java
@@ -80,10 +80,29 @@
}
/**
- * Load delegate items if any in the data model
+ * Load hot seat items if any in the data model
*/
@WorkerThread
- public void loadItems(UserManagerState ums, Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
+ public void loadHotseatItems(UserManagerState ums,
+ Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
+
+ /**
+ * Load all apps items if any in the data model
+ */
+ @WorkerThread
+ public void loadAllAppsItems(UserManagerState ums,
+ Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
+
+ /**
+ * Load widget recommendation items if any in the data model
+ */
+ @WorkerThread
+ public void loadWidgetsRecommendationItems() { }
+
+ /**
+ * Marks the ModelDelegate as active
+ */
+ public void markActive() { }
/**
* Load String cache
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 6444ef6..7ab86ad 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -18,6 +18,9 @@
import static androidx.test.InstrumentationRegistry.getContext;
+import static com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_ID;
+import static com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_PROVIDER;
+import static com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_SOURCE;
import static com.android.launcher3.LauncherSettings.Favorites.CELLX;
import static com.android.launcher3.LauncherSettings.Favorites.CELLY;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER;
@@ -30,9 +33,13 @@
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+import static com.android.launcher3.LauncherSettings.Favorites.OPTIONS;
import static com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID;
+import static com.android.launcher3.LauncherSettings.Favorites.RANK;
import static com.android.launcher3.LauncherSettings.Favorites.RESTORED;
import static com.android.launcher3.LauncherSettings.Favorites.SCREEN;
+import static com.android.launcher3.LauncherSettings.Favorites.SPANX;
+import static com.android.launcher3.LauncherSettings.Favorites.SPANY;
import static com.android.launcher3.LauncherSettings.Favorites.TITLE;
import static com.android.launcher3.LauncherSettings.Favorites._ID;
import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
@@ -92,7 +99,9 @@
mCursor = new MatrixCursor(new String[] {
ICON, ICON_PACKAGE, ICON_RESOURCE, TITLE,
_ID, CONTAINER, ITEM_TYPE, PROFILE_ID,
- SCREEN, CELLX, CELLY, RESTORED, INTENT
+ SCREEN, CELLX, CELLY, RESTORED, INTENT,
+ APPWIDGET_ID, APPWIDGET_PROVIDER, SPANX,
+ SPANY, RANK, OPTIONS, APPWIDGET_SOURCE
});
UserManagerState ums = new UserManagerState();