Load Delegate Items in correct order when loading Launcher Data.
Bug: 251502424
Test: Loaded and bound the workspace properly.
Change-Id: Ia6d609ffa21c5036cb48e464d3e8d4fa561cb008
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index 2e1318b..bc97df1 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -48,11 +48,15 @@
import android.util.Log;
import android.util.StatsEvent;
+import androidx.annotation.AnyThread;
+import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
@@ -62,6 +66,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.util.Executors;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.PersistedItemArray;
import com.android.quickstep.logging.SettingsChangeLogger;
@@ -111,45 +116,80 @@
mStatsManager = context.getSystemService(StatsManager.class);
}
+ @CallSuper
@Override
- public void loadHotseatItems(UserManagerState ums,
- Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
- // TODO: Implement caching and preloading
- 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);
+ public void loadAndBindWorkspaceItems(@NonNull UserManagerState ums,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
+ loadAndBindItems(ums, pinnedShortcuts, callbacks, mIDP.numDatabaseHotseatIcons,
+ mHotseatState);
}
+ @CallSuper
@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);
- FixedContainerItems allAppsPredictionItems = new FixedContainerItems(
- mAllAppsState.containerId, mAllAppsState.storage.read(mApp.getContext(),
- allAppsFactory, ums.allUsers::get));
- mDataModel.extraItems.put(mAllAppsState.containerId, allAppsPredictionItems);
+ public void loadAndBindAllAppsItems(@NonNull UserManagerState ums,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
+ loadAndBindItems(ums, pinnedShortcuts, callbacks, mIDP.numDatabaseAllAppsColumns,
+ mAllAppsState);
}
- @Override
- public void loadWidgetsRecommendationItems() {
+ @WorkerThread
+ private void loadAndBindItems(@NonNull UserManagerState ums,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ int numColumns, @NonNull PredictorState state) {
// TODO: Implement caching and preloading
- super.loadWidgetsRecommendationItems();
+
+ WorkspaceItemFactory factory =
+ new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, numColumns, state.containerId);
+ FixedContainerItems fci = new FixedContainerItems(state.containerId,
+ state.storage.read(mApp.getContext(), factory, ums.allUsers::get));
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ bindPredictionItems(callbacks, fci);
+ }
+ mDataModel.extraItems.put(state.containerId, fci);
+ }
+
+ @CallSuper
+ @Override
+ public void loadAndBindOtherItems(@NonNull BgDataModel.Callbacks[] callbacks) {
+ FixedContainerItems widgetPredictionFCI = new FixedContainerItems(
+ mWidgetsRecommendationState.containerId, new ArrayList<>());
// 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<>()));
+ mDataModel.extraItems.put(mWidgetsRecommendationState.containerId, widgetPredictionFCI);
+
+ bindPredictionItems(callbacks, widgetPredictionFCI);
+ loadStringCache(mDataModel.stringCache);
+ }
+
+ @AnyThread
+ private void bindPredictionItems(@NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull FixedContainerItems fci) {
+ Executors.MAIN_EXECUTOR.execute(() -> {
+ for (BgDataModel.Callbacks c : callbacks) {
+ c.bindExtraContainerItems(fci);
+ }
+ });
}
@Override
+ @WorkerThread
+ public void bindAllModelExtras(@NonNull BgDataModel.Callbacks[] callbacks) {
+ Iterable<FixedContainerItems> containerItems;
+ synchronized (mDataModel.extraItems) {
+ containerItems = mDataModel.extraItems.clone();
+ }
+ Executors.MAIN_EXECUTOR.execute(() -> {
+ for (BgDataModel.Callbacks c : callbacks) {
+ for (FixedContainerItems fci : containerItems) {
+ c.bindExtraContainerItems(fci);
+ }
+ }
+ });
+ }
+
public void markActive() {
super.markActive();
mActive = true;
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index ad95f7e..06ac44a 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -421,6 +421,9 @@
launcherBinder.bindAllApps();
launcherBinder.bindDeepShortcuts();
launcherBinder.bindWidgets();
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.bindAllModelExtras(callbacksList);
+ }
return true;
} else {
stopLoader();
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 6f1dfe9..ead81d6 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -380,6 +380,11 @@
"load the current workspace screen visible to the user before the rest rather than "
+ "loading all of them at once.");
+ public static final BooleanFlag CHANGE_MODEL_DELEGATE_LOADING_ORDER = getDebugFlag(251502424,
+ "CHANGE_MODEL_DELEGATE_LOADING_ORDER", DISABLED,
+ "changes the timing of the loading and binding of delegate items during "
+ + "data preparation for loading the home screen");
+
public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206,
"ENABLE_GRID_ONLY_OVERVIEW", DISABLED,
"Enable a grid-only overview without a focused task.");
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index 0767e69..372e9bf 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -229,8 +229,8 @@
query += " or " + LauncherSettings.Favorites.SCREEN + " = "
+ Workspace.SECOND_SCREEN_ID;
}
- loadWorkspace(new ArrayList<>(), LauncherSettings.Favorites.PREVIEW_CONTENT_URI,
- query);
+ loadWorkspaceForPreviewSurfaceRenderer(new ArrayList<>(),
+ LauncherSettings.Favorites.PREVIEW_CONTENT_URI, query);
final SparseArray<Size> spanInfo =
getLoadedLauncherWidgetInfo(previewContext.getBaseContext());
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index 91ace27..358992e 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -63,7 +63,7 @@
protected final BgDataModel mBgDataModel;
private final AllAppsList mBgAllAppsList;
- private final Callbacks[] mCallbacksList;
+ final Callbacks[] mCallbacksList;
private int mMyBindingId;
@@ -293,8 +293,10 @@
// Load items on the current page.
bindWorkspaceItems(currentWorkspaceItems, mUiExecutor);
bindAppWidgets(currentAppWidgets, mUiExecutor);
- mExtraItems.forEach(item ->
- executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor));
+ if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mExtraItems.forEach(item ->
+ executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor));
+ }
RunnableList pendingTasks = new RunnableList();
Executor pendingExecutor = pendingTasks::add;
@@ -382,14 +384,22 @@
// Save a copy of all the bg-thread collections
ArrayList<ItemInfo> workspaceItems;
ArrayList<LauncherAppWidgetInfo> appWidgets;
+ ArrayList<FixedContainerItems> fciList = new ArrayList<>();
synchronized (mBgDataModel) {
workspaceItems = new ArrayList<>(mBgDataModel.workspaceItems);
appWidgets = new ArrayList<>(mBgDataModel.appWidgets);
+ if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mBgDataModel.extraItems.forEach(fciList::add);
+ }
}
workspaceItems.forEach(it -> mBoundItemIds.add(it.id));
appWidgets.forEach(it -> mBoundItemIds.add(it.id));
+ if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ fciList.forEach(item ->
+ executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor));
+ }
sortWorkspaceItemsSpatially(mApp.getInvariantDeviceProfile(), workspaceItems);
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index da9be49..f8376e8 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -138,6 +138,7 @@
private final UserManagerState mUserManagerState = new UserManagerState();
protected final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap = new ArrayMap<>();
+ private Map<ShortcutKey, ShortcutInfo> mShortcutKeyToPinnedShortcuts;
private boolean mStopped;
@@ -211,6 +212,14 @@
}
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.
// sanitizeData should not be invoked if the workspace is loaded from a db different
// from the main db as defined in the invariant device profile.
@@ -246,6 +255,11 @@
}
logASplit(timingLogger, "loadAllApps");
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.loadAndBindAllAppsItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ logASplit(timingLogger, "allAppsDelegateItems");
+ }
verifyNotStopped();
mLauncherBinder.bindAllApps();
logASplit(timingLogger, "bindAllApps");
@@ -296,6 +310,12 @@
logASplit(timingLogger, "bindWidgets");
verifyNotStopped();
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);
+ logASplit(timingLogger, "otherDelegateItems");
+ verifyNotStopped();
+ }
+
updateHandler.updateIcons(allWidgetsList,
new ComponentWithIconCachingLogic(mApp.getContext(), true),
mApp.getModel()::onWidgetLabelsUpdated);
@@ -334,9 +354,14 @@
null /* selection */, memoryLogger);
}
- protected void loadWorkspace(
+ protected void loadWorkspaceForPreviewSurfaceRenderer(
List<ShortcutInfo> allDeepShortcuts, Uri contentUri, String selection) {
loadWorkspace(allDeepShortcuts, contentUri, selection, null);
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.markActive();
+ }
}
protected void loadWorkspace(
@@ -376,7 +401,7 @@
final PackageUserKey tempPackageKey = new PackageUserKey(null, null);
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
- Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts = new HashMap<>();
+ mShortcutKeyToPinnedShortcuts = new HashMap<>();
final LoaderCursor c = new LoaderCursor(
contentResolver.query(contentUri, null, selection, null, null), contentUri,
mApp, mUserManagerState);
@@ -397,7 +422,7 @@
.query(ShortcutRequest.PINNED);
if (pinnedShortcuts.wasSuccess()) {
for (ShortcutInfo shortcut : pinnedShortcuts) {
- shortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut),
+ mShortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut),
shortcut);
}
} else {
@@ -414,7 +439,7 @@
while (!mStopped && c.moveToNext()) {
processWorkspaceItem(c, memoryLogger, installingPkgs, isSdCardReady,
- tempPackageKey, widgetHelper, pmHelper, shortcutKeyToPinnedShortcuts,
+ tempPackageKey, widgetHelper, pmHelper,
iconRequestInfos, unlockedUsers, isSafeMode, allDeepShortcuts);
}
maybeLoadWorkspaceIconsInBulk(iconRequestInfos);
@@ -422,14 +447,14 @@
IOUtils.closeSilently(c);
}
- // Load delegate items
- mModelDelegate.loadHotseatItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
- mModelDelegate.loadAllAppsItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
- mModelDelegate.loadWidgetsRecommendationItems();
- mModelDelegate.markActive();
-
- // Load string cache
- mModelDelegate.loadStringCache(mBgDataModel.stringCache);
+ if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.loadAndBindAllAppsItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);
+ mModelDelegate.markActive();
+ }
// Break early if we've stopped loading
if (mStopped) {
@@ -474,7 +499,6 @@
PackageUserKey tempPackageKey,
WidgetManagerHelper widgetHelper,
PackageManagerHelper pmHelper,
- Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts,
List<IconRequestInfo<WorkspaceItemInfo>> iconRequestInfos,
LongSparseArray<Boolean> unlockedUsers,
boolean isSafeMode,
@@ -603,7 +627,7 @@
} 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);
+ ShortcutInfo pinnedShortcut = mShortcutKeyToPinnedShortcuts.get(key);
if (pinnedShortcut == null) {
// The shortcut is no longer valid.
c.markDeleted("Pinned shortcut not found");
diff --git a/src/com/android/launcher3/model/ModelDelegate.java b/src/com/android/launcher3/model/ModelDelegate.java
index 0639a6c..7e7bfb3 100644
--- a/src/com/android/launcher3/model/ModelDelegate.java
+++ b/src/com/android/launcher3/model/ModelDelegate.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.pm.ShortcutInfo;
+import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherAppState;
@@ -68,9 +69,7 @@
this.mContext = context;
}
- /**
- * Called periodically to validate and update any data
- */
+ /** Called periodically to validate and update any data */
@WorkerThread
public void validateData() {
if (hasShortcutsPermission(mApp.getContext())
@@ -79,36 +78,32 @@
}
}
- /**
- * Load hot seat items if any in the data model
- */
+ /** Load workspace items (for example, those in the hot seat) if any in the data model */
@WorkerThread
- public void loadHotseatItems(UserManagerState ums,
- Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
+ public void loadAndBindWorkspaceItems(@NonNull UserManagerState ums,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
- /**
- * Load all apps items if any in the data model
- */
+ /** Load all apps items if any in the data model */
@WorkerThread
- public void loadAllAppsItems(UserManagerState ums,
- Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
+ public void loadAndBindAllAppsItems(@NonNull UserManagerState ums,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
- /**
- * Load widget recommendation items if any in the data model
- */
+ /** Load other items like widget recommendations if any in the data model */
@WorkerThread
- public void loadWidgetsRecommendationItems() { }
+ public void loadAndBindOtherItems(@NonNull BgDataModel.Callbacks[] callbacks) { }
- /**
- * Marks the ModelDelegate as active
- */
+ /** binds everything not bound by launcherBinder */
+ @WorkerThread
+ public void bindAllModelExtras(@NonNull BgDataModel.Callbacks[] callbacks) { }
+
+ /** Marks the ModelDelegate as active */
public void markActive() { }
- /**
- * Load String cache
- */
+ /** Load String cache */
@WorkerThread
- public void loadStringCache(StringCache cache) {
+ public void loadStringCache(@NonNull StringCache cache) {
cache.loadStrings(mContext);
}