Converting ModelTask to an interface instead of an abstract class

This allows extensibility and better use of lambdas

Bug: 338282246
Test: Presubmit
Flag: None

Change-Id: Ia41067f0068b3b631eeb4faf877dc77f8587e1f6
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 9b0e0ec..be98589 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -48,7 +48,6 @@
 import com.android.launcher3.model.AddWorkspaceItemsTask;
 import com.android.launcher3.model.AllAppsList;
 import com.android.launcher3.model.BaseLauncherBinder;
-import com.android.launcher3.model.BaseModelUpdateTask;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.model.CacheDataUpdatedTask;
@@ -57,6 +56,7 @@
 import com.android.launcher3.model.ModelDbController;
 import com.android.launcher3.model.ModelDelegate;
 import com.android.launcher3.model.ModelLauncherCallbacks;
+import com.android.launcher3.model.ModelTaskController;
 import com.android.launcher3.model.ModelWriter;
 import com.android.launcher3.model.PackageInstallStateChangedTask;
 import com.android.launcher3.model.PackageUpdatedTask;
@@ -82,7 +82,6 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.CancellationException;
-import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
@@ -426,13 +425,9 @@
     @Override
     public void onInstallSessionCreated(@NonNull final PackageInstallInfo sessionInfo) {
         if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
-            enqueueModelUpdateTask(new BaseModelUpdateTask() {
-                @Override
-                public void execute(@NonNull final LauncherAppState app,
-                        @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                    apps.addPromiseApp(app.getContext(), sessionInfo);
-                    bindApplicationsIfNeeded();
-                }
+            enqueueModelUpdateTask((taskController, dataModel, apps) -> {
+                apps.addPromiseApp(mApp.getContext(), sessionInfo);
+                taskController.bindApplicationsIfNeeded();
             });
         }
     }
@@ -440,60 +435,56 @@
     @Override
     public void onSessionFailure(@NonNull final String packageName,
             @NonNull final UserHandle user) {
-        enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                IconCache iconCache = app.getIconCache();
-                final IntSet removedIds = new IntSet();
-                HashSet<WorkspaceItemInfo> archivedWorkspaceItemsToCacheRefresh = new HashSet<>();
-                boolean isAppArchived = PackageManagerHelper.INSTANCE.get(mApp.getContext())
-                        .isAppArchivedForUser(packageName, user);
-                synchronized (dataModel) {
-                    if (isAppArchived) {
-                        // Remove package icon cache entry for archived app in case of a session
-                        // failure.
-                        mApp.getIconCache().remove(
-                                new ComponentName(packageName, packageName + EMPTY_CLASS_NAME),
-                                user);
-                    }
+        enqueueModelUpdateTask((taskController, dataModel, apps) -> {
+            IconCache iconCache = mApp.getIconCache();
+            final IntSet removedIds = new IntSet();
+            HashSet<WorkspaceItemInfo> archivedWorkspaceItemsToCacheRefresh = new HashSet<>();
+            boolean isAppArchived = PackageManagerHelper.INSTANCE.get(mApp.getContext())
+                    .isAppArchivedForUser(packageName, user);
+            synchronized (dataModel) {
+                if (isAppArchived) {
+                    // Remove package icon cache entry for archived app in case of a session
+                    // failure.
+                    mApp.getIconCache().remove(
+                            new ComponentName(packageName, packageName + EMPTY_CLASS_NAME),
+                            user);
+                }
 
-                    for (ItemInfo info : dataModel.itemsIdMap) {
-                        if (info instanceof WorkspaceItemInfo
-                                && ((WorkspaceItemInfo) info).hasPromiseIconUi()
-                                && user.equals(info.user)
-                                && info.getIntent() != null) {
-                            if (TextUtils.equals(packageName, info.getIntent().getPackage())) {
-                                removedIds.add(info.id);
-                            }
-                            if (((WorkspaceItemInfo) info).isArchived()) {
-                                WorkspaceItemInfo workspaceItem = (WorkspaceItemInfo) info;
-                                // Refresh icons on the workspace for archived apps.
-                                iconCache.getTitleAndIcon(workspaceItem,
-                                        workspaceItem.usingLowResIcon());
-                                archivedWorkspaceItemsToCacheRefresh.add(workspaceItem);
-                            }
+                for (ItemInfo info : dataModel.itemsIdMap) {
+                    if (info instanceof WorkspaceItemInfo
+                            && ((WorkspaceItemInfo) info).hasPromiseIconUi()
+                            && user.equals(info.user)
+                            && info.getIntent() != null) {
+                        if (TextUtils.equals(packageName, info.getIntent().getPackage())) {
+                            removedIds.add(info.id);
+                        }
+                        if (((WorkspaceItemInfo) info).isArchived()) {
+                            WorkspaceItemInfo workspaceItem = (WorkspaceItemInfo) info;
+                            // Refresh icons on the workspace for archived apps.
+                            iconCache.getTitleAndIcon(workspaceItem,
+                                    workspaceItem.usingLowResIcon());
+                            archivedWorkspaceItemsToCacheRefresh.add(workspaceItem);
                         }
                     }
-
-                    if (isAppArchived) {
-                        apps.updateIconsAndLabels(new HashSet<>(List.of(packageName)), user);
-                    }
                 }
 
-                if (!removedIds.isEmpty()) {
-                    deleteAndBindComponentsRemoved(
-                            ItemInfoMatcher.ofItemIds(removedIds),
-                            "removed because install session failed");
-                }
-                if (!archivedWorkspaceItemsToCacheRefresh.isEmpty()) {
-                    bindUpdatedWorkspaceItems(
-                            archivedWorkspaceItemsToCacheRefresh.stream().toList());
-                }
                 if (isAppArchived) {
-                    bindApplicationsIfNeeded();
+                    apps.updateIconsAndLabels(new HashSet<>(List.of(packageName)), user);
                 }
             }
+
+            if (!removedIds.isEmpty()) {
+                taskController.deleteAndBindComponentsRemoved(
+                        ItemInfoMatcher.ofItemIds(removedIds),
+                        "removed because install session failed");
+            }
+            if (!archivedWorkspaceItemsToCacheRefresh.isEmpty()) {
+                taskController.bindUpdatedWorkspaceItems(
+                        archivedWorkspaceItemsToCacheRefresh.stream().toList());
+            }
+            if (isAppArchived) {
+                taskController.bindApplicationsIfNeeded();
+            }
         });
     }
 
@@ -583,13 +574,9 @@
      */
     public void onWidgetLabelsUpdated(@NonNull final HashSet<String> updatedPackages,
             @NonNull final UserHandle user) {
-        enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                dataModel.widgetsModel.onPackageIconsUpdated(updatedPackages, user, app);
-                bindUpdatedWidgets(dataModel);
-            }
+        enqueueModelUpdateTask((taskController, dataModel, apps) ->  {
+            dataModel.widgetsModel.onPackageIconsUpdated(updatedPackages, user, mApp);
+            taskController.bindUpdatedWidgets(dataModel);
         });
     }
 
@@ -597,8 +584,15 @@
         if (mModelDestroyed) {
             return;
         }
-        task.init(mApp, this, mBgDataModel, mBgAllAppsList, MAIN_EXECUTOR);
-        MODEL_EXECUTOR.execute(task);
+        MODEL_EXECUTOR.execute(() -> {
+            if (!isModelLoaded()) {
+                // Loader has not yet run.
+                return;
+            }
+            ModelTaskController controller = new ModelTaskController(
+                    mApp, mBgDataModel, mBgAllAppsList, this, MAIN_EXECUTOR);
+            task.execute(controller, mBgDataModel, mBgAllAppsList);
+        });
     }
 
     /**
@@ -610,18 +604,10 @@
         void execute(@NonNull Callbacks callbacks);
     }
 
-    /**
-     * A runnable which changes/updates the data model of the launcher based on certain events.
-     */
-    public interface ModelUpdateTask extends Runnable {
+    public interface ModelUpdateTask {
 
-        /**
-         * Called before the task is posted to initialize the internal state.
-         */
-        void init(@NonNull LauncherAppState app, @NonNull LauncherModel model,
-                @NonNull BgDataModel dataModel, @NonNull AllAppsList allAppsList,
-                @NonNull Executor uiExecutor);
-
+        void execute(@NonNull ModelTaskController taskController,
+                @NonNull BgDataModel dataModel, @NonNull AllAppsList apps);
     }
 
     public void updateAndBindWorkspaceItem(@NonNull final WorkspaceItemInfo si,
@@ -638,27 +624,19 @@
      */
     public void updateAndBindWorkspaceItem(
             @NonNull final Supplier<WorkspaceItemInfo> itemProvider) {
-        enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                WorkspaceItemInfo info = itemProvider.get();
-                getModelWriter().updateItemInDatabase(info);
-                ArrayList<WorkspaceItemInfo> update = new ArrayList<>();
-                update.add(info);
-                bindUpdatedWorkspaceItems(update);
-            }
+        enqueueModelUpdateTask((taskController, dataModel, apps) ->  {
+            WorkspaceItemInfo info = itemProvider.get();
+            taskController.getModelWriter().updateItemInDatabase(info);
+            ArrayList<WorkspaceItemInfo> update = new ArrayList<>();
+            update.add(info);
+            taskController.bindUpdatedWorkspaceItems(update);
         });
     }
 
     public void refreshAndBindWidgetsAndShortcuts(@Nullable final PackageUserKey packageUser) {
-        enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                dataModel.widgetsModel.update(app, packageUser);
-                bindUpdatedWidgets(dataModel);
-            }
+        enqueueModelUpdateTask((taskController, dataModel, apps) ->  {
+            dataModel.widgetsModel.update(taskController.getApp(), packageUser);
+            taskController.bindUpdatedWidgets(dataModel);
         });
     }