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/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);
     }