From 42975c39db39cc83b198a3e458016e3e87df0353 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 28 Feb 2025 15:56:15 -0800 Subject: [PATCH] Making various model objects injectable Bug: 361850561 Test: Updated tests Flag: EXEMPT dagger Change-Id: Ibb45b72c186e6aeeed7a37b0ae3f8083472019d7 --- .../launcher3/WidgetPickerActivity.java | 12 +- .../launcher3/model/PredictionUpdateTask.java | 15 +- .../model/WidgetsPredictionUpdateTask.java | 2 +- .../model/QuickstepModelDelegateTest.kt | 2 +- src/com/android/launcher3/LauncherModel.kt | 57 ++---- .../dagger/LauncherBaseAppComponent.java | 3 + .../graphics/LauncherPreviewRenderer.java | 6 + .../graphics/PreviewSurfaceRenderer.java | 60 +++--- .../model/AddWorkspaceItemsTask.java | 13 +- .../android/launcher3/model/AllAppsList.java | 10 +- .../launcher3/model/BaseLauncherBinder.java | 73 ++++---- .../android/launcher3/model/BgDataModel.java | 14 +- .../launcher3/model/CacheDataUpdatedTask.java | 2 +- .../launcher3/model/FirstScreenBroadcast.java | 6 +- .../android/launcher3/model/LoaderCursor.java | 48 +++-- .../android/launcher3/model/LoaderTask.java | 172 ++++++++++-------- .../launcher3/model/ModelLauncherCallbacks.kt | 4 +- .../launcher3/model/ModelTaskController.kt | 21 ++- .../model/PackageInstallStateChangedTask.java | 4 +- .../launcher3/model/PackageUpdatedTask.java | 8 +- .../model/SdCardAvailableReceiver.java | 8 +- .../launcher3/model/SessionFailureTask.kt | 4 +- .../launcher3/model/ShortcutsChangedTask.kt | 5 +- .../model/UserLockStateChangedTask.java | 6 +- .../android/launcher3/model/WidgetsModel.java | 70 ++++--- .../launcher3/model/WorkspaceItemProcessor.kt | 24 +-- .../model/WorkspaceItemSpaceFinder.java | 35 ++-- .../launcher3/provider/LauncherDbUtils.kt | 7 +- .../android/launcher3/util/ItemInflater.kt | 10 +- .../launcher3/widget/WidgetInflater.kt | 16 +- .../model/AddWorkspaceItemsTaskTest.kt | 10 +- .../launcher3/model/LoaderCursorTest.java | 9 +- .../launcher3/model/PackageUpdatedTaskTest.kt | 64 +++++-- .../model/ShortcutsChangedTaskTest.kt | 19 +- .../launcher3/model/WidgetsModelTest.kt | 12 +- .../model/WorkspaceItemProcessorTest.kt | 71 +++----- .../model/WorkspaceItemSpaceFinderTest.kt | 13 +- .../android/launcher3/model/LoaderTaskTest.kt | 95 ++++++---- .../model/WorkspaceItemProcessorExtraTest.kt | 96 +++++----- 39 files changed, 601 insertions(+), 505 deletions(-) diff --git a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java index 4d3e3bea67..cdae9caa5c 100644 --- a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java +++ b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java @@ -166,7 +166,7 @@ public class WidgetPickerActivity extends BaseActivity implements mApp = LauncherAppState.getInstance(this); InvariantDeviceProfile idp = mApp.getInvariantDeviceProfile(); mDeviceProfile = idp.getDeviceProfile(this); - mModel = new WidgetsModel(); + mModel = new WidgetsModel(mApp.getContext()); mWidgetPickerDataProvider = new WidgetPickerDataProvider(this); setContentView(R.layout.widget_picker_activity); @@ -309,8 +309,7 @@ public class WidgetPickerActivity extends BaseActivity implements */ private void refreshAndBindWidgets() { MODEL_EXECUTOR.execute(() -> { - LauncherAppState app = LauncherAppState.getInstance(this); - mModel.update(app, null); + mModel.update(null); StringCache stringCache = new StringCache(); stringCache.loadStrings(this); @@ -321,9 +320,10 @@ public class WidgetPickerActivity extends BaseActivity implements // animation. openWidgetsSheet(); if (mUiSurface != null) { - mWidgetPredictionsRequester = new WidgetPredictionsRequester(app.getContext(), - mUiSurface, mModel.getWidgetsByComponentKeyForPicker()); - mWidgetPredictionsRequester.request(mAddedWidgets, /*listener=*/ this); + mWidgetPredictionsRequester = new WidgetPredictionsRequester( + getApplicationContext(), mUiSurface, + mModel.getWidgetsByComponentKeyForPicker()); + mWidgetPredictionsRequester.request(mAddedWidgets, this); } }); } diff --git a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java index fd71151bbe..3544844bd2 100644 --- a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java +++ b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java @@ -32,9 +32,9 @@ import android.os.UserHandle; import androidx.annotation.NonNull; import com.android.launcher3.ConstantItem; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel.ModelUpdateTask; import com.android.launcher3.LauncherPrefs; +import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.QuickstepModelDelegate.PredictorState; import com.android.launcher3.model.data.AppInfo; @@ -65,8 +65,8 @@ public class PredictionUpdateTask implements ModelUpdateTask { @Override public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel, @NonNull AllAppsList apps) { - LauncherAppState app = taskController.getApp(); - Context context = app.getContext(); + IconCache iconCache = taskController.getIconCache(); + Context context = taskController.getContext(); // TODO: remove this LauncherPrefs.get(context).put(LAST_PREDICTION_ENABLED, !mTargets.isEmpty()); @@ -84,7 +84,7 @@ public class PredictionUpdateTask implements ModelUpdateTask { if (si != null) { usersForChangedShortcuts.add(si.getUserHandle()); itemInfo = new WorkspaceItemInfo(si, context); - app.getIconCache().getShortcutIcon(itemInfo, si); + iconCache.getShortcutIcon(itemInfo, si); } else { String className = target.getClassName(); if (COMPONENT_CLASS_MARKER.equals(className)) { @@ -96,7 +96,7 @@ public class PredictionUpdateTask implements ModelUpdateTask { itemInfo = apps.data.stream() .filter(info -> user.equals(info.user) && cn.equals(info.componentName)) .map(ai -> { - app.getIconCache().getTitleAndIcon(ai, mPredictorState.lookupFlag); + iconCache.getTitleAndIcon(ai, mPredictorState.lookupFlag); return ai.makeWorkspaceItem(context); }) .findAny() @@ -107,7 +107,7 @@ public class PredictionUpdateTask implements ModelUpdateTask { return null; } AppInfo ai = new AppInfo(context, lai, user); - app.getIconCache().getTitleAndIcon(ai, lai, DEFAULT_LOOKUP_FLAG); + iconCache.getTitleAndIcon(ai, lai, DEFAULT_LOOKUP_FLAG); return ai.makeWorkspaceItem(context); }); @@ -123,8 +123,7 @@ public class PredictionUpdateTask implements ModelUpdateTask { FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId, items); dataModel.extraItems.put(fci.containerId, fci); taskController.bindExtraContainerItems(fci); - usersForChangedShortcuts.forEach( - u -> dataModel.updateShortcutPinnedState(app.getContext(), u)); + usersForChangedShortcuts.forEach(u -> dataModel.updateShortcutPinnedState(context, u)); // Save to disk mPredictorState.storage.write(context, fci.items); diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java index 0a4b7c8d19..da55b40b19 100644 --- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java +++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java @@ -82,7 +82,7 @@ public final class WidgetsPredictionUpdateTask implements ModelUpdateTask { && !widgetsInWorkspace.contains(entry.getValue()) ).collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); - Context context = taskController.getApp().getContext(); + Context context = taskController.getContext(); List servicePredictedItems = new ArrayList<>(); List addedWidgetApps = new ArrayList<>(); diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/model/QuickstepModelDelegateTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/QuickstepModelDelegateTest.kt index 09c62aae1a..1c7af14667 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/model/QuickstepModelDelegateTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/QuickstepModelDelegateTest.kt @@ -64,7 +64,7 @@ class QuickstepModelDelegateTest { underTest.mHotseatState.predictor = hotseatPredictor underTest.mWidgetsRecommendationState.predictor = widgetRecommendationPredictor underTest.mModel = modelHelper.model - underTest.mDataModel = BgDataModel() + underTest.mDataModel = BgDataModel(WidgetsModel(modelHelper.sandboxContext)) } @After diff --git a/src/com/android/launcher3/LauncherModel.kt b/src/com/android/launcher3/LauncherModel.kt index add0ad843c..02d70ae386 100644 --- a/src/com/android/launcher3/LauncherModel.kt +++ b/src/com/android/launcher3/LauncherModel.kt @@ -28,11 +28,12 @@ import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.icons.IconCache import com.android.launcher3.model.AddWorkspaceItemsTask import com.android.launcher3.model.AllAppsList -import com.android.launcher3.model.BaseLauncherBinder +import com.android.launcher3.model.BaseLauncherBinder.BaseLauncherBinderFactory import com.android.launcher3.model.BgDataModel import com.android.launcher3.model.CacheDataUpdatedTask import com.android.launcher3.model.ItemInstallQueue import com.android.launcher3.model.LoaderTask +import com.android.launcher3.model.LoaderTask.LoaderTaskFactory import com.android.launcher3.model.ModelDbController import com.android.launcher3.model.ModelDelegate import com.android.launcher3.model.ModelInitializer @@ -43,6 +44,8 @@ import com.android.launcher3.model.PackageUpdatedTask import com.android.launcher3.model.ReloadStringCacheTask import com.android.launcher3.model.ShortcutsChangedTask import com.android.launcher3.model.UserLockStateChangedTask +import com.android.launcher3.model.UserManagerState +import com.android.launcher3.model.WorkspaceItemSpaceFinder import com.android.launcher3.model.data.ItemInfo import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.pm.UserCache @@ -70,28 +73,23 @@ class LauncherModel @Inject constructor( @ApplicationContext private val context: Context, - private val appProvider: Provider, + private val taskControllerProvider: Provider, private val iconCache: IconCache, private val prefs: LauncherPrefs, private val installQueue: ItemInstallQueue, - appFilter: AppFilter, @Named("ICONS_DB") dbFileName: String?, initializer: ModelInitializer, lifecycle: DaggerSingletonTracker, val modelDelegate: ModelDelegate, + private val mBgAllAppsList: AllAppsList, + private val mBgDataModel: BgDataModel, + private val loaderFactory: LoaderTaskFactory, + private val binderFactory: BaseLauncherBinderFactory, + private val spaceFinderFactory: Provider, ) { private val mCallbacksList = ArrayList(1) - // < only access in worker thread > - private val mBgAllAppsList = AllAppsList(iconCache, appFilter) - - /** - * All the static data should be accessed on the background thread, A lock should be acquired on - * this object when accessing any data from this model. - */ - private val mBgDataModel = BgDataModel() - val modelDbController = ModelDbController(context) private val mLock = Any() @@ -139,7 +137,7 @@ constructor( /** Adds the provided items to the workspace. */ fun addAndBindAddedWorkspaceItems(itemList: List?>) { callbacks.forEach { it.preAddApps() } - enqueueModelUpdateTask(AddWorkspaceItemsTask(itemList)) + enqueueModelUpdateTask(AddWorkspaceItemsTask(itemList, spaceFinderFactory.get())) } fun getWriter( @@ -299,13 +297,7 @@ constructor( // Clear any pending bind-runnables from the synchronized load process. callbacksList.forEach { MAIN_EXECUTOR.execute(it::clearPendingBinds) } - val launcherBinder = - BaseLauncherBinder( - appProvider.get(), - mBgDataModel, - mBgAllAppsList, - callbacksList, - ) + val launcherBinder = binderFactory.createBinder(callbacksList) if (bindDirectly) { // Divide the set of loaded items into those that we are binding synchronously, // and everything else that is to be bound normally (asynchronously). @@ -317,14 +309,7 @@ constructor( launcherBinder.bindWidgets() return true } else { - val task = - LoaderTask( - appProvider.get(), - mBgAllAppsList, - mBgDataModel, - this.modelDelegate, - launcherBinder, - ) + val task = loaderFactory.newLoaderTask(launcherBinder, UserManagerState()) mLoaderTask = task // Always post the loader task, instead of running directly @@ -425,7 +410,7 @@ constructor( /** Called when the labels for the widgets has updated in the icon cache. */ fun onWidgetLabelsUpdated(updatedPackages: HashSet, user: UserHandle) { enqueueModelUpdateTask { taskController, dataModel, _ -> - dataModel.widgetsModel.onPackageIconsUpdated(updatedPackages, user, appProvider.get()) + dataModel.widgetsModel.onPackageIconsUpdated(updatedPackages, user) taskController.bindUpdatedWidgets(dataModel) } } @@ -439,17 +424,7 @@ constructor( // Loader has not yet run. return@execute } - task.execute( - ModelTaskController( - appProvider.get(), - mBgDataModel, - mBgAllAppsList, - this, - MAIN_EXECUTOR, - ), - mBgDataModel, - mBgAllAppsList, - ) + task.execute(taskControllerProvider.get(), mBgDataModel, mBgAllAppsList) } } @@ -476,7 +451,7 @@ constructor( fun refreshAndBindWidgetsAndShortcuts(packageUser: PackageUserKey?) { enqueueModelUpdateTask { taskController, dataModel, _ -> - dataModel.widgetsModel.update(taskController.app, packageUser) + dataModel.widgetsModel.update(packageUser) taskController.bindUpdatedWidgets(dataModel) } } diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java index 06643d3cbf..c49909772e 100644 --- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java +++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java @@ -28,6 +28,7 @@ import com.android.launcher3.graphics.GridCustomizationsProxy; import com.android.launcher3.graphics.ThemeManager; import com.android.launcher3.icons.LauncherIcons.IconPool; import com.android.launcher3.model.ItemInstallQueue; +import com.android.launcher3.model.LoaderCursor.LoaderCursorFactory; import com.android.launcher3.model.WidgetsFilterDataProvider; import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.pm.UserCache; @@ -87,6 +88,8 @@ public interface LauncherBaseAppComponent { GridCustomizationsProxy getGridCustomizationsProxy(); WidgetsFilterDataProvider getWidgetsFilterDataProvider(); + LoaderCursorFactory getLoaderCursorFactory(); + /** Builder for LauncherBaseAppComponent. */ interface Builder { @BindsInstance Builder appContext(@ApplicationContext Context context); diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index b80238cb1e..e4e4b900fa 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -80,8 +80,10 @@ import com.android.launcher3.dagger.LauncherAppComponent; import com.android.launcher3.dagger.LauncherAppModule; import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.launcher3.folder.FolderIcon; +import com.android.launcher3.model.BaseLauncherBinder.BaseLauncherBinderFactory; import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.BgDataModel.FixedContainerItems; +import com.android.launcher3.model.LoaderTask.LoaderTaskFactory; import com.android.launcher3.model.data.AppPairInfo; import com.android.launcher3.model.data.CollectionInfo; import com.android.launcher3.model.data.FolderInfo; @@ -605,6 +607,10 @@ public class LauncherPreviewRenderer extends BaseContext @Component(modules = LauncherAppModule.class) public interface PreviewAppComponent extends LauncherAppComponent { + LoaderTaskFactory getLoaderTaskFactory(); + BaseLauncherBinderFactory getBaseLauncherBinderFactory(); + BgDataModel getDataModel(); + /** Builder for NexusLauncherAppComponent. */ @Component.Builder interface Builder extends LauncherAppComponent.Builder { diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java index d425f03712..5a9b9c20f9 100644 --- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java @@ -58,19 +58,21 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Workspace; +import com.android.launcher3.dagger.LauncherComponentProvider; +import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewAppComponent; import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewContext; -import com.android.launcher3.model.BaseLauncherBinder; import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.LoaderTask; import com.android.launcher3.model.ModelDbController; +import com.android.launcher3.model.UserManagerState; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.Themes; import com.android.launcher3.widget.LocalColorExtractor; import com.android.systemui.shared.Flags; -import java.util.ArrayList; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -338,38 +340,32 @@ public class PreviewSurfaceRenderer { // Start the migration PreviewContext previewContext = new PreviewContext(inflationContext, mGridName, mShapeKey); + PreviewAppComponent appComponent = + (PreviewAppComponent) LauncherComponentProvider.get(previewContext); - BgDataModel bgModel = new BgDataModel(); - new LoaderTask( - LauncherAppState.getInstance(previewContext), - /* bgAllAppsList= */ null, - bgModel, - LauncherAppState.getInstance(previewContext).getModel().getModelDelegate(), - new BaseLauncherBinder(LauncherAppState.getInstance(previewContext), bgModel, - /* bgAllAppsList= */ null, new Callbacks[0])) { + LoaderTask task = appComponent.getLoaderTaskFactory().newLoaderTask( + appComponent.getBaseLauncherBinderFactory().createBinder(new Callbacks[0]), + new UserManagerState()); - @Override - public void run() { - InvariantDeviceProfile idp = LauncherAppState.getIDP(previewContext); - DeviceProfile deviceProfile = idp.getDeviceProfile(previewContext); - String query = - LauncherSettings.Favorites.SCREEN + " = " + Workspace.FIRST_SCREEN_ID - + " or " + LauncherSettings.Favorites.CONTAINER + " = " - + LauncherSettings.Favorites.CONTAINER_HOTSEAT; - if (deviceProfile.isTwoPanels) { - query += " or " + LauncherSettings.Favorites.SCREEN + " = " - + Workspace.SECOND_SCREEN_ID; - } - loadWorkspace(new ArrayList<>(), query, null, null); + InvariantDeviceProfile idp = appComponent.getIDP(); + DeviceProfile deviceProfile = idp.getDeviceProfile(previewContext); + String query = + LauncherSettings.Favorites.SCREEN + " = " + Workspace.FIRST_SCREEN_ID + + " or " + LauncherSettings.Favorites.CONTAINER + " = " + + LauncherSettings.Favorites.CONTAINER_HOTSEAT; + if (deviceProfile.isTwoPanels) { + query += " or " + LauncherSettings.Favorites.SCREEN + " = " + + Workspace.SECOND_SCREEN_ID; + } - final SparseArray spanInfo = getLoadedLauncherWidgetInfo(); - MAIN_EXECUTOR.execute(() -> { - renderView(previewContext, mBgDataModel, mWidgetProvidersMap, spanInfo, - idp); - mLifeCycleTracker.add(previewContext::onDestroy); - }); - } - }.run(); + Map widgetProviderInfoMap = new HashMap<>(); + task.loadWorkspaceForPreview(query, widgetProviderInfoMap); + final SparseArray spanInfo = getLoadedLauncherWidgetInfo(); + MAIN_EXECUTOR.execute(() -> { + renderView(previewContext, appComponent.getDataModel(), widgetProviderInfoMap, + spanInfo, idp); + mLifeCycleTracker.add(previewContext::onDestroy); + }); } else { LauncherAppState.getInstance(inflationContext).getModel().loadAsync(dataModel -> { if (dataModel != null) { @@ -420,7 +416,6 @@ public class PreviewSurfaceRenderer { view.setTranslationY((mHeight - scale * view.getHeight()) / 2); } - if (!Flags.newCustomizationPickerUi()) { view.setAlpha(mSkipAnimations ? 1 : 0); view.animate().alpha(1) @@ -477,5 +472,4 @@ public class PreviewSurfaceRenderer { MAIN_EXECUTOR.execute(mLifecycleTracker::executeAllAndDestroy); } } - } diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java index ddbbdc722a..dfba4bb192 100644 --- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java +++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java @@ -64,13 +64,6 @@ public class AddWorkspaceItemsTask implements ModelUpdateTask { @NonNull private final WorkspaceItemSpaceFinder mItemSpaceFinder; - /** - * @param itemList items to add on the workspace - */ - public AddWorkspaceItemsTask(@NonNull final List> itemList) { - this(itemList, new WorkspaceItemSpaceFinder()); - } - /** * @param itemList items to add on the workspace * @param itemSpaceFinder inject WorkspaceItemSpaceFinder dependency for testing @@ -91,7 +84,7 @@ public class AddWorkspaceItemsTask implements ModelUpdateTask { final ArrayList addedItemsFinal = new ArrayList<>(); final IntArray addedWorkspaceScreensFinal = new IntArray(); - final Context context = taskController.getApp().getContext(); + final Context context = taskController.getContext(); synchronized (dataModel) { IntArray workspaceScreens = dataModel.collectWorkspaceScreens(); @@ -133,7 +126,7 @@ public class AddWorkspaceItemsTask implements ModelUpdateTask { for (ItemInfo item : filteredItems) { // Find appropriate space for the item. - int[] coords = mItemSpaceFinder.findSpaceForItem(taskController.getApp(), dataModel, + int[] coords = mItemSpaceFinder.findSpaceForItem( workspaceScreens, addedWorkspaceScreensFinal, item.spanX, item.spanY); int screenId = coords[0]; @@ -192,7 +185,7 @@ public class AddWorkspaceItemsTask implements ModelUpdateTask { continue; } - IconCache cache = taskController.getApp().getIconCache(); + IconCache cache = taskController.getIconCache(); WorkspaceItemInfo wii = (WorkspaceItemInfo) itemInfo; wii.title = ""; wii.bitmap = cache.getDefaultIcon(item.user); diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java index 98f9afdaaa..2311239025 100644 --- a/src/com/android/launcher3/model/AllAppsList.java +++ b/src/com/android/launcher3/model/AllAppsList.java @@ -34,6 +34,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.AppFilter; import com.android.launcher3.compat.AlphabeticIndexCompat; +import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.data.AppInfo; @@ -53,11 +54,13 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; +import javax.inject.Inject; + /** * Stores the list of all applications for the all apps view. */ -@SuppressWarnings("NewApi") +@LauncherAppSingleton public class AllAppsList { private static final String TAG = "AllAppsList"; @@ -70,10 +73,10 @@ public class AllAppsList { public final ArrayList data = new ArrayList<>(DEFAULT_APPLICATIONS_NUMBER); @NonNull - private IconCache mIconCache; + private final IconCache mIconCache; @NonNull - private AppFilter mAppFilter; + private final AppFilter mAppFilter; private boolean mDataChanged = false; private Consumer mRemoveListener = NO_OP_CONSUMER; @@ -92,6 +95,7 @@ public class AllAppsList { /** * Boring constructor. */ + @Inject public AllAppsList(IconCache iconCache, AppFilter appFilter) { mIconCache = iconCache; mAppFilter = appFilter; diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java index 262bf678c7..c4bbae416b 100644 --- a/src/com/android/launcher3/model/BaseLauncherBinder.java +++ b/src/com/android/launcher3/model/BaseLauncherBinder.java @@ -26,6 +26,7 @@ import static com.android.launcher3.model.ModelUtils.currentScreenContentFilter; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import android.content.Context; import android.os.Trace; import android.util.Log; import android.util.Pair; @@ -34,11 +35,12 @@ import android.view.View; import androidx.annotation.NonNull; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherModel.CallbackTask; import com.android.launcher3.LauncherSettings; import com.android.launcher3.celllayout.CellPosMapper; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dagger.ApplicationContext; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.data.AppInfo; @@ -55,6 +57,10 @@ import com.android.launcher3.util.RunnableList; import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder; import com.android.launcher3.widget.model.WidgetsListBaseEntry; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -76,7 +82,9 @@ public class BaseLauncherBinder { protected final LooperExecutor mUiExecutor; - protected final LauncherAppState mApp; + private final Context mContext; + private final InvariantDeviceProfile mIDP; + private final LauncherModel mModel; protected final BgDataModel mBgDataModel; private final AllAppsList mBgAllAppsList; @@ -84,10 +92,18 @@ public class BaseLauncherBinder { private int mMyBindingId; - public BaseLauncherBinder(LauncherAppState app, BgDataModel dataModel, - AllAppsList allAppsList, Callbacks[] callbacksList) { + @AssistedInject + public BaseLauncherBinder( + @ApplicationContext Context context, + InvariantDeviceProfile idp, + LauncherModel model, + BgDataModel dataModel, + AllAppsList allAppsList, + @Assisted Callbacks[] callbacksList) { mUiExecutor = MAIN_EXECUTOR; - mApp = app; + mContext = context; + mIDP = idp; + mModel = model; mBgDataModel = dataModel; mBgAllAppsList = allAppsList; mCallbacksList = callbacksList; @@ -110,15 +126,14 @@ public class BaseLauncherBinder { mBgDataModel.extraItems.forEach(extraItems::add); if (incrementBindId) { mBgDataModel.lastBindId++; - mBgDataModel.lastLoadId = mApp.getModel().getLastLoadId(); + mBgDataModel.lastLoadId = mModel.getLastLoadId(); } mMyBindingId = mBgDataModel.lastBindId; workspaceItemCount = mBgDataModel.itemsIdMap.size(); } for (Callbacks cb : mCallbacksList) { - new UnifiedWorkspaceBinder(cb, mUiExecutor, mApp, mBgDataModel, mMyBindingId, - itemsIdMap, extraItems, orderedScreenIds) + new UnifiedWorkspaceBinder(cb, itemsIdMap, extraItems, orderedScreenIds) .bind(isBindSync, workspaceItemCount); } } finally { @@ -162,9 +177,8 @@ public class BaseLauncherBinder { if (!WIDGETS_ENABLED) { return; } - List widgets = new WidgetsListBaseEntriesBuilder(mApp.getContext()) + List widgets = new WidgetsListBaseEntriesBuilder(mContext) .build(mBgDataModel.widgetsModel.getWidgetsByPackageItemForPicker()); - executeCallbacksTask(c -> c.bindAllWidgets(widgets), mUiExecutor); } @@ -181,10 +195,9 @@ public class BaseLauncherBinder { /** * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right) */ - protected void sortWorkspaceItemsSpatially(InvariantDeviceProfile profile, - ArrayList workspaceItems) { - final int screenCols = profile.numColumns; - final int screenCellCount = profile.numColumns * profile.numRows; + protected void sortWorkspaceItemsSpatially(ArrayList workspaceItems) { + final int screenCols = mIDP.numColumns; + final int screenCellCount = mIDP.numColumns * mIDP.numRows; Collections.sort(workspaceItems, (lhs, rhs) -> { if (lhs.container == rhs.container) { // Within containers, order by their spatial position in that container @@ -240,30 +253,18 @@ public class BaseLauncherBinder { private class UnifiedWorkspaceBinder { - private final Executor mUiExecutor; private final Callbacks mCallbacks; - private final LauncherAppState mApp; - private final BgDataModel mBgDataModel; - - private final int mMyBindingId; private final IntSparseArrayMap mItemIdMap; private final IntArray mOrderedScreenIds; private final ArrayList mExtraItems; - UnifiedWorkspaceBinder(Callbacks callbacks, - Executor uiExecutor, - LauncherAppState app, - BgDataModel bgDataModel, - int myBindingId, + UnifiedWorkspaceBinder( + Callbacks callbacks, IntSparseArrayMap itemIdMap, ArrayList extraItems, IntArray orderedScreenIds) { mCallbacks = callbacks; - mUiExecutor = uiExecutor; - mApp = app; - mBgDataModel = bgDataModel; - mMyBindingId = myBindingId; mItemIdMap = itemIdMap; mExtraItems = extraItems; mOrderedScreenIds = orderedScreenIds; @@ -289,9 +290,8 @@ public class BaseLauncherBinder { (WIDGET_FILTER.test(item) ? otherAppWidgets : otherWorkspaceItems).add(item); } }); - final InvariantDeviceProfile idp = mApp.getInvariantDeviceProfile(); - sortWorkspaceItemsSpatially(idp, currentWorkspaceItems); - sortWorkspaceItemsSpatially(idp, otherWorkspaceItems); + sortWorkspaceItemsSpatially(currentWorkspaceItems); + sortWorkspaceItemsSpatially(otherWorkspaceItems); // Tell the workspace that we're about to start binding items executeCallbacksTask(c -> { @@ -352,7 +352,7 @@ public class BaseLauncherBinder { executeCallbacksTask(c -> c.bindStringCache(cacheClone), pendingExecutor); executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor); - pendingExecutor.execute(() -> ItemInstallQueue.INSTANCE.get(mApp.getContext()) + pendingExecutor.execute(() -> ItemInstallQueue.INSTANCE.get(mContext) .resumeModelPush(FLAG_LOADER_RUNNING)); } @@ -367,8 +367,8 @@ public class BaseLauncherBinder { return; } - ModelWriter writer = mApp.getModel() - .getWriter(false /* verifyChanges */, CellPosMapper.DEFAULT, null); + ModelWriter writer = mModel.getWriter( + false /* verifyChanges */, CellPosMapper.DEFAULT, null); List> bindItems = items.stream() .map(i -> Pair.create(i, inflater.inflateItem(i, writer, null))) .collect(Collectors.toList()); @@ -398,4 +398,9 @@ public class BaseLauncherBinder { }); } } + + @AssistedFactory + public interface BaseLauncherBinderFactory { + BaseLauncherBinder createBinder(Callbacks[] callbacks); + } } diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java index d9eccaf4f3..ea9f36c419 100644 --- a/src/com/android/launcher3/model/BgDataModel.java +++ b/src/com/android/launcher3/model/BgDataModel.java @@ -46,6 +46,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.BuildConfig; import com.android.launcher3.Workspace; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.CollectionInfo; @@ -79,9 +80,15 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.inject.Inject; + /** * All the data stored in-memory and managed by the LauncherModel + * + * All the static data should be accessed on the background thread, A lock should be acquired on + * this object when accessing any data from this model. */ +@LauncherAppSingleton public class BgDataModel { private static final String TAG = "BgDataModel"; @@ -105,7 +112,7 @@ public class BgDataModel { /** * Entire list of widgets. */ - public final WidgetsModel widgetsModel = new WidgetsModel(); + public final WidgetsModel widgetsModel; /** * Cache for strings used in launcher @@ -124,6 +131,11 @@ public class BgDataModel { public boolean isFirstPagePinnedItemEnabled = QSB_ON_FIRST_SCREEN && !enableSmartspaceRemovalToggle(); + @Inject + public BgDataModel(WidgetsModel widgetsModel) { + this.widgetsModel = widgetsModel; + } + /** * Clears all the data */ diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java index 48934e2c11..f740b49694 100644 --- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java +++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java @@ -59,7 +59,7 @@ public class CacheDataUpdatedTask implements ModelUpdateTask { @Override public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel, @NonNull AllAppsList apps) { - IconCache iconCache = taskController.getApp().getIconCache(); + IconCache iconCache = taskController.getIconCache(); ArrayList updatedItems = new ArrayList<>(); synchronized (dataModel) { diff --git a/src/com/android/launcher3/model/FirstScreenBroadcast.java b/src/com/android/launcher3/model/FirstScreenBroadcast.java index f443f8142e..829e0fe08b 100644 --- a/src/com/android/launcher3/model/FirstScreenBroadcast.java +++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java @@ -45,9 +45,9 @@ import com.android.launcher3.util.PackageUserKey; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -76,9 +76,9 @@ public class FirstScreenBroadcast { private static final String VERIFICATION_TOKEN_EXTRA = "verificationToken"; - private final HashMap mSessionInfoForPackage; + private final Map mSessionInfoForPackage; - public FirstScreenBroadcast(HashMap sessionInfoForPackage) { + public FirstScreenBroadcast(Map sessionInfoForPackage) { mSessionInfoForPackage = sessionInfoForPackage; } diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java index bd8c36b576..77d0d7656b 100644 --- a/src/com/android/launcher3/model/LoaderCursor.java +++ b/src/com/android/launcher3/model/LoaderCursor.java @@ -45,13 +45,14 @@ import androidx.annotation.VisibleForTesting; import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; import com.android.launcher3.backuprestore.LauncherRestoreEventLogger; import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dagger.ApplicationContext; import com.android.launcher3.icons.IconCache; import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.data.AppInfo; @@ -70,6 +71,10 @@ import com.android.launcher3.util.IntSparseArrayMap; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.UserIconInfo; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; + import java.net.URISyntaxException; import java.security.InvalidParameterException; @@ -82,8 +87,8 @@ public class LoaderCursor extends CursorWrapper { private final LongSparseArray allUsers; - private final LauncherAppState mApp; private final Context mContext; + private final LauncherModel mModel; private final PackageManagerHelper mPmHelper; private final IconCache mIconCache; private final InvariantDeviceProfile mIDP; @@ -130,17 +135,24 @@ public class LoaderCursor extends CursorWrapper { public int itemType; public int restoreFlag; - public LoaderCursor(Cursor cursor, LauncherAppState app, UserManagerState userManagerState, - PackageManagerHelper pmHelper, - @Nullable LauncherRestoreEventLogger restoreEventLogger) { + @AssistedInject + public LoaderCursor( + @Assisted Cursor cursor, + @Assisted UserManagerState userManagerState, + @Assisted @Nullable LauncherRestoreEventLogger restoreEventLogger, + @ApplicationContext Context context, + IconCache iconCache, + InvariantDeviceProfile idp, + LauncherModel model, + PackageManagerHelper pmHelper) { super(cursor); - - mApp = app; - allUsers = userManagerState.allUsers; - mContext = app.getContext(); - mIconCache = app.getIconCache(); + mContext = context; + mIconCache = iconCache; + mIDP = idp; + mModel = model; mPmHelper = pmHelper; - mIDP = app.getInvariantDeviceProfile(); + + allUsers = userManagerState.allUsers; mRestoreEventLogger = restoreEventLogger; // Init column indices @@ -432,7 +444,7 @@ public class LoaderCursor extends CursorWrapper { */ public ContentWriter updater() { return new ContentWriter(mContext, new ContentWriter.CommitParams( - mApp.getModel().getModelDbController(), + mModel.getModelDbController(), BaseColumns._ID + "= ?", new String[]{Integer.toString(id)})); } @@ -454,7 +466,7 @@ public class LoaderCursor extends CursorWrapper { public boolean commitDeleted() { if (mItemsToRemove.size() > 0) { // Remove dead items - mApp.getModel().getModelDbController().delete(TABLE_NAME, + mModel.getModelDbController().delete(TABLE_NAME, Utilities.createDbSelectionQuery(Favorites._ID, mItemsToRemove), null); return true; } @@ -480,7 +492,7 @@ public class LoaderCursor extends CursorWrapper { // Update restored items that no longer require special handling ContentValues values = new ContentValues(); values.put(Favorites.RESTORED, 0); - mApp.getModel().getModelDbController().update(TABLE_NAME, values, + mModel.getModelDbController().update(TABLE_NAME, values, Utilities.createDbSelectionQuery(Favorites._ID, mRestoredRows), null); } if (mRestoreEventLogger != null) { @@ -645,4 +657,12 @@ public class LoaderCursor extends CursorWrapper { return false; } } + + @AssistedFactory + public interface LoaderCursorFactory { + + LoaderCursor createLoaderCursor(Cursor cursor, + UserManagerState userManagerState, + @Nullable LauncherRestoreEventLogger restoreEventLogger); + } } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index fb1ebaf3c4..73af6a221a 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -53,7 +53,6 @@ import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; -import android.util.ArrayMap; import android.util.Log; import android.util.LongSparseArray; @@ -63,13 +62,14 @@ import androidx.annotation.VisibleForTesting; import androidx.annotation.WorkerThread; import com.android.launcher3.Flags; -import com.android.launcher3.LauncherAppState; +import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; import com.android.launcher3.backuprestore.LauncherRestoreEventLogger; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dagger.ApplicationContext; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderGridOrganizer; import com.android.launcher3.folder.FolderNameInfos; @@ -82,6 +82,7 @@ import com.android.launcher3.icons.cache.CachedObjectCachingLogic; import com.android.launcher3.icons.cache.IconCacheUpdateHandler; import com.android.launcher3.icons.cache.LauncherActivityCachingLogic; import com.android.launcher3.logging.FileLog; +import com.android.launcher3.model.LoaderCursor.LoaderCursorFactory; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.AppPairInfo; import com.android.launcher3.model.data.FolderInfo; @@ -106,6 +107,10 @@ import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.widget.WidgetInflater; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -117,6 +122,8 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CancellationException; +import javax.inject.Named; + /** * Runnable for the thread that loads the contents of the launcher: * - workspace icons @@ -131,10 +138,14 @@ public class LoaderTask implements Runnable { private static final boolean DEBUG = true; - @NonNull - protected final LauncherAppState mApp; + private final Context mContext; + private final LauncherModel mModel; + private final InvariantDeviceProfile mIDP; + private final boolean mIsSafeModeEnabled; private final AllAppsList mBgAllAppsList; protected final BgDataModel mBgDataModel; + private final LoaderCursorFactory mLoaderCursorFactory; + private final ModelDelegate mModelDelegate; private boolean mIsRestoreFromBackup; @@ -152,7 +163,6 @@ public class LoaderTask implements Runnable { private final IconCache mIconCache; private final UserManagerState mUserManagerState; - protected final Map mWidgetProvidersMap = new ArrayMap<>(); private Map mShortcutKeyToPinnedShortcuts; private HashMap mInstallingPkgsCached; @@ -164,26 +174,36 @@ public class LoaderTask implements Runnable { private boolean mItemsDeleted = false; private String mDbName; - public LoaderTask(@NonNull LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel bgModel, - ModelDelegate modelDelegate, @NonNull BaseLauncherBinder launcherBinder) { - this(app, bgAllAppsList, bgModel, modelDelegate, launcherBinder, new UserManagerState()); - } - - @VisibleForTesting - LoaderTask(@NonNull LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel bgModel, - ModelDelegate modelDelegate, @NonNull BaseLauncherBinder launcherBinder, - UserManagerState userManagerState) { - mApp = app; + @AssistedInject + LoaderTask( + @ApplicationContext Context context, + InvariantDeviceProfile idp, + LauncherModel model, + UserCache userCache, + PackageManagerHelper pmHelper, + InstallSessionHelper sessionHelper, + IconCache iconCache, + AllAppsList bgAllAppsList, + BgDataModel bgModel, + LoaderCursorFactory loaderCursorFactory, + @Named("SAFE_MODE") boolean isSafeModeEnabled, + @Assisted @NonNull BaseLauncherBinder launcherBinder, + @Assisted UserManagerState userManagerState) { + mContext = context; + mIDP = idp; + mModel = model; + mIsSafeModeEnabled = isSafeModeEnabled; mBgAllAppsList = bgAllAppsList; mBgDataModel = bgModel; - mModelDelegate = modelDelegate; + mModelDelegate = model.getModelDelegate(); mLauncherBinder = launcherBinder; - mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class); - mUserManager = mApp.getContext().getSystemService(UserManager.class); - mUserCache = UserCache.INSTANCE.get(mApp.getContext()); - mPmHelper = PackageManagerHelper.INSTANCE.get(mApp.getContext()); - mSessionHelper = InstallSessionHelper.INSTANCE.get(mApp.getContext()); - mIconCache = mApp.getIconCache(); + mLoaderCursorFactory = loaderCursorFactory; + mLauncherApps = mContext.getSystemService(LauncherApps.class); + mUserManager = mContext.getSystemService(UserManager.class); + mUserCache = userCache; + mPmHelper = pmHelper; + mSessionHelper = sessionHelper; + mIconCache = iconCache; mUserManagerState = userManagerState; mInstallingPkgsCached = null; } @@ -215,7 +235,7 @@ public class LoaderTask implements Runnable { .filter(currentScreenContentFilter(firstScreens)) .toList(); final int disableArchivingLauncherBroadcast = Settings.Secure.getInt( - mApp.getContext().getContentResolver(), + mContext.getContentResolver(), "disable_launcher_broadcast_installed_apps", /* default */ 0); boolean shouldAttachArchivingExtras = mIsRestoreFromBackup @@ -230,10 +250,10 @@ public class LoaderTask implements Runnable { mBgDataModel.itemsIdMap.stream().filter(WIDGET_FILTER).toList() ); logASplit("Sending first screen broadcast with additional archiving Extras"); - FirstScreenBroadcastHelper.sendBroadcastsForModels(mApp.getContext(), broadcastModels); + FirstScreenBroadcastHelper.sendBroadcastsForModels(mContext, broadcastModels); } else { logASplit("Sending first screen broadcast"); - mFirstScreenBroadcast.sendBroadcasts(mApp.getContext(), firstScreenItems); + mFirstScreenBroadcast.sendBroadcasts(mContext, firstScreenItems); } } @@ -249,16 +269,14 @@ public class LoaderTask implements Runnable { MODEL_EXECUTOR.elevatePriority(CALLER_LOADER_TASK); LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger(); mIsRestoreFromBackup = - LauncherPrefs.get(mApp.getContext()).get(IS_FIRST_LOAD_AFTER_RESTORE); + LauncherPrefs.get(mContext).get(IS_FIRST_LOAD_AFTER_RESTORE); LauncherRestoreEventLogger restoreEventLogger = null; if (enableLauncherBrMetricsFixed()) { - restoreEventLogger = LauncherRestoreEventLogger.Companion - .newInstance(mApp.getContext()); + restoreEventLogger = LauncherRestoreEventLogger.Companion.newInstance(mContext); } - try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { - + try (LauncherModel.LoaderTransaction transaction = mModel.beginLoader(this)) { List allShortcuts = new ArrayList<>(); - loadWorkspace(allShortcuts, "", memoryLogger, restoreEventLogger); + loadWorkspace(allShortcuts, "", new HashMap<>(), memoryLogger, restoreEventLogger); // 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 @@ -267,7 +285,7 @@ public class LoaderTask implements Runnable { // TODO(b/384731096): Write Unit Test to make sure sanitizeWidgetsShortcutsAndPackages // actually re-pins shortcuts that are in model but not in ShortcutManager, if possible // after a simulated restore. - if (Objects.equals(mApp.getInvariantDeviceProfile().dbFile, mDbName)) { + if (Objects.equals(mIDP.dbFile, mDbName)) { verifyNotStopped(); sanitizeFolders(mItemsDeleted); sanitizeAppPairs(); @@ -307,13 +325,13 @@ public class LoaderTask implements Runnable { setIgnorePackages(updateHandler); updateHandler.updateIcons(allActivityList, LauncherActivityCachingLogic.INSTANCE, - mApp.getModel()::onPackageIconsUpdated); + mModel::onPackageIconsUpdated); logASplit("update AllApps icon cache finished"); verifyNotStopped(); logASplit("saving all shortcuts in icon cache"); updateHandler.updateIcons(allShortcuts, CacheableShortcutCachingLogic.INSTANCE, - mApp.getModel()::onPackageIconsUpdated); + mModel::onPackageIconsUpdated); // Take a break waitForIdle(); @@ -342,14 +360,14 @@ public class LoaderTask implements Runnable { // fourth step WidgetsModel widgetsModel = mBgDataModel.widgetsModel; - List allWidgetsList = widgetsModel.update(mApp, /*packageUser=*/null); + List allWidgetsList = widgetsModel.update(/*packageUser=*/null); logASplit("load widgets finished"); verifyNotStopped(); mLauncherBinder.bindWidgets(); logASplit("bindWidgets finished"); verifyNotStopped(); - LauncherPrefs prefs = LauncherPrefs.get(mApp.getContext()); + LauncherPrefs prefs = LauncherPrefs.get(mContext); if (enableSmartspaceAsAWidget() && prefs.get(SHOULD_SHOW_SMARTSPACE)) { mLauncherBinder.bindSmartspaceWidget(); @@ -366,7 +384,7 @@ public class LoaderTask implements Runnable { logASplit("saving all widgets in icon cache"); updateHandler.updateIcons(allWidgetsList, CachedObjectCachingLogic.INSTANCE, - mApp.getModel()::onWidgetLabelsUpdated); + mModel::onWidgetLabelsUpdated); // fifth step loadFolderNames(); @@ -380,7 +398,7 @@ public class LoaderTask implements Runnable { memoryLogger.clearLogs(); if (mIsRestoreFromBackup) { mIsRestoreFromBackup = false; - LauncherPrefs.get(mApp.getContext()).putSync(IS_FIRST_LOAD_AFTER_RESTORE.to(false)); + LauncherPrefs.get(mContext).putSync(IS_FIRST_LOAD_AFTER_RESTORE.to(false)); if (restoreEventLogger != null) { restoreEventLogger.reportLauncherRestoreResults(); } @@ -402,35 +420,42 @@ public class LoaderTask implements Runnable { this.notify(); } - protected void loadWorkspace( + public void loadWorkspaceForPreview(String selection, + Map widgetProviderInfoMap) { + loadWorkspace(new ArrayList<>(), selection, widgetProviderInfoMap, null, null); + } + + private void loadWorkspace( List allDeepShortcuts, String selection, + Map widgetProviderInfoMap, @Nullable LoaderMemoryLogger memoryLogger, @Nullable LauncherRestoreEventLogger restoreEventLogger ) { Trace.beginSection("LoadWorkspace"); try { - loadWorkspaceImpl(allDeepShortcuts, selection, memoryLogger, restoreEventLogger); + loadWorkspaceImpl(allDeepShortcuts, selection, widgetProviderInfoMap, + memoryLogger, restoreEventLogger); } finally { Trace.endSection(); } logASplit("loadWorkspace finished"); mBgDataModel.isFirstPagePinnedItemEnabled = FeatureFlags.QSB_ON_FIRST_SCREEN - && (!enableSmartspaceRemovalToggle() || LauncherPrefs.getPrefs( - mApp.getContext()).getBoolean(SMARTSPACE_ON_HOME_SCREEN, true)); + && (!enableSmartspaceRemovalToggle() + || LauncherPrefs.getPrefs(mContext).getBoolean(SMARTSPACE_ON_HOME_SCREEN, true)); } private void loadWorkspaceImpl( List allDeepShortcuts, String selection, + Map widgetProviderInfoMap, @Nullable LoaderMemoryLogger memoryLogger, @Nullable LauncherRestoreEventLogger restoreEventLogger) { - final Context context = mApp.getContext(); final boolean isSdCardReady = Utilities.isBootCompleted(); - final WidgetInflater widgetInflater = new WidgetInflater(context); + final WidgetInflater widgetInflater = new WidgetInflater(mContext, mIsSafeModeEnabled); - ModelDbController dbController = mApp.getModel().getModelDbController(); + ModelDbController dbController = mModel.getModelDbController(); if (Flags.gridMigrationRefactor()) { try { dbController.attemptMigrateDb(restoreEventLogger, mModelDelegate); @@ -452,28 +477,29 @@ public class LoaderTask implements Runnable { if (Flags.enableSupportForArchiving()) { mInstallingPkgsCached = installingPkgs; } - installingPkgs.forEach(mApp.getIconCache()::updateSessionCache); + installingPkgs.forEach(mIconCache::updateSessionCache); FileLog.d(TAG, "loadWorkspace: Packages with active install/update sessions: " + installingPkgs.keySet().stream().map(info -> info.mPackageName).toList()); mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs); mShortcutKeyToPinnedShortcuts = new HashMap<>(); - final LoaderCursor c = new LoaderCursor( + final LoaderCursor c = mLoaderCursorFactory.createLoaderCursor( dbController.query(TABLE_NAME, null, selection, null, null), - mApp, mUserManagerState, mPmHelper, + mUserManagerState, mIsRestoreFromBackup ? restoreEventLogger : null); final Bundle extras = c.getExtras(); mDbName = extras == null ? null : extras.getString(ModelDbController.EXTRA_DB_NAME); try { final LongSparseArray unlockedUsers = new LongSparseArray<>(); - queryPinnedShortcutsForUnlockedUsers(context, unlockedUsers); + queryPinnedShortcutsForUnlockedUsers(mContext, unlockedUsers); mWorkspaceIconRequestInfos = new ArrayList<>(); WorkspaceItemProcessor itemProcessor = new WorkspaceItemProcessor(c, memoryLogger, mUserCache, mUserManagerState, mLauncherApps, mPendingPackages, - mShortcutKeyToPinnedShortcuts, mApp, mBgDataModel, - mWidgetProvidersMap, installingPkgs, isSdCardReady, + mShortcutKeyToPinnedShortcuts, mContext, mIDP, mIconCache, + mIsSafeModeEnabled, mBgDataModel, + widgetProviderInfoMap, installingPkgs, isSdCardReady, widgetInflater, mPmHelper, mWorkspaceIconRequestInfos, unlockedUsers, allDeepShortcuts); @@ -577,7 +603,7 @@ public class LoaderTask implements Runnable { @WorkerThread private void processFolderItems() { // Sort the folder items, update ranks, and make sure all preview items are high res. - List verifiers = mApp.getInvariantDeviceProfile().supportedProfiles + List verifiers = mIDP.supportedProfiles .stream().map(FolderGridOrganizer::createFolderGridOrganizer).toList(); for (ItemInfo itemInfo : mBgDataModel.itemsIdMap) { if (!(itemInfo instanceof FolderInfo folder)) { @@ -617,7 +643,7 @@ public class LoaderTask implements Runnable { if (mIconCache.isDefaultIcon(wai.bitmap, wai.user)) { logASplit("tryLoadWorkspaceIconsInBulk: default icon found for " + wai.getTargetComponent() + ", will attempt to load from iconBlob"); - iconRequestInfo.loadIconFromDbBlob(mApp.getContext()); + iconRequestInfo.loadIconFromDbBlob(mContext); } } } finally { @@ -649,7 +675,7 @@ public class LoaderTask implements Runnable { private void sanitizeFolders(boolean itemsDeleted) { if (itemsDeleted) { // Remove any empty folder - IntArray deletedFolderIds = mApp.getModel().getModelDbController().deleteEmptyFolders(); + IntArray deletedFolderIds = mModel.getModelDbController().deleteEmptyFolders(); synchronized (mBgDataModel) { for (int folderId : deletedFolderIds) { mBgDataModel.itemsIdMap.remove(folderId); @@ -660,8 +686,8 @@ public class LoaderTask implements Runnable { /** Cleans up app pairs if they don't have the right number of member apps (2). */ private void sanitizeAppPairs() { - IntArray deletedAppPairIds = mApp.getModel().getModelDbController().deleteBadAppPairs(); - IntArray deletedAppIds = mApp.getModel().getModelDbController().deleteUnparentedApps(); + IntArray deletedAppPairIds = mModel.getModelDbController().deleteBadAppPairs(); + IntArray deletedAppIds = mModel.getModelDbController().deleteUnparentedApps(); IntArray deleted = new IntArray(); deleted.addAll(deletedAppPairIds); @@ -675,17 +701,15 @@ public class LoaderTask implements Runnable { } private void sanitizeWidgetsShortcutsAndPackages() { - Context context = mApp.getContext(); - // Remove any ghost widgets - mApp.getModel().getModelDbController().removeGhostWidgets(); + mModel.getModelDbController().removeGhostWidgets(); // Update pinned state of model shortcuts - mBgDataModel.updateShortcutPinnedState(context); + mBgDataModel.updateShortcutPinnedState(mContext); if (!Utilities.isBootCompleted() && !mPendingPackages.isEmpty()) { - context.registerReceiver( - new SdCardAvailableReceiver(mApp, mPendingPackages), + mContext.registerReceiver( + new SdCardAvailableReceiver(mContext, mModel, mPendingPackages), new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, MODEL_EXECUTOR.getHandler()); @@ -722,7 +746,7 @@ public class LoaderTask implements Runnable { for (int i = 0; i < apps.size(); i++) { LauncherActivityInfo app = apps.get(i); AppInfo appInfo = new AppInfo(app, mUserCache.getUserInfo(user), - ApiWrapper.INSTANCE.get(mApp.getContext()), mPmHelper, quietMode); + ApiWrapper.INSTANCE.get(mContext), mPmHelper, quietMode); if (Flags.enableSupportForArchiving() && app.getApplicationInfo().isArchived) { // For archived apps, include progress info in case there is a pending // install session post restart of device. @@ -751,7 +775,7 @@ public class LoaderTask implements Runnable { for (PackageInstaller.SessionInfo info : mSessionHelper.getAllVerifiedSessions()) { AppInfo promiseAppInfo = mBgAllAppsList.addPromiseApp( - mApp.getContext(), + mContext, PackageInstallInfo.fromInstallingState(info), false); @@ -776,7 +800,7 @@ public class LoaderTask implements Runnable { + appInfo.getTargetComponent() + ", will attempt to load from iconBlob: " + Arrays.toString(iconRequestInfo.iconBlob)); - iconRequestInfo.loadIconFromDbBlob(mApp.getContext()); + iconRequestInfo.loadIconFromDbBlob(mContext); } } } @@ -794,9 +818,9 @@ public class LoaderTask implements Runnable { mUserManagerState.isAnyProfileQuietModeEnabled()); } mBgAllAppsList.setFlags(FLAG_HAS_SHORTCUT_PERMISSION, - hasShortcutsPermission(mApp.getContext())); + hasShortcutsPermission(mContext)); mBgAllAppsList.setFlags(FLAG_QUIET_MODE_CHANGE_PERMISSION, - mApp.getContext().checkSelfPermission("android.permission.MODIFY_QUIET_MODE") + mContext.checkSelfPermission("android.permission.MODIFY_QUIET_MODE") == PackageManager.PERMISSION_GRANTED); mBgAllAppsList.getAndResetChangeFlag(); @@ -827,7 +851,7 @@ public class LoaderTask implements Runnable { workspaceIconRequest.get().iconBlob, false /* useLowResIcon= */ ); - if (!iconRequestInfo.loadIconFromDbBlob(mApp.getContext())) { + if (!iconRequestInfo.loadIconFromDbBlob(mContext)) { Log.d(TAG, "AppInfo Icon failed to load from blob, using cache."); mIconCache.getTitleAndIcon( appInfo, @@ -853,7 +877,7 @@ public class LoaderTask implements Runnable { if (mBgAllAppsList.hasShortcutHostPermission()) { for (UserHandle user : mUserCache.getUserProfiles()) { if (mUserManager.isUserUnlocked(user)) { - List shortcuts = new ShortcutRequest(mApp.getContext(), user) + List shortcuts = new ShortcutRequest(mContext, user) .query(ShortcutRequest.ALL); allShortcuts.addAll(shortcuts); mBgDataModel.updateDeepShortcutCounts(null, user, shortcuts); @@ -864,7 +888,7 @@ public class LoaderTask implements Runnable { } private void loadFolderNames() { - FolderNameProvider provider = FolderNameProvider.newInstance(mApp.getContext(), + FolderNameProvider provider = FolderNameProvider.newInstance(mContext, mBgAllAppsList.data, FolderNameProvider.getCollectionForSuggestions(mBgDataModel)); synchronized (mBgDataModel) { @@ -874,7 +898,7 @@ public class LoaderTask implements Runnable { .forEach(info -> { FolderInfo fi = (FolderInfo) info; FolderNameInfos suggestionInfos = new FolderNameInfos(); - provider.getSuggestedFolderName(mApp.getContext(), fi.getAppContents(), + provider.getSuggestedFolderName(mContext, fi.getAppContents(), suggestionInfos); fi.suggestedFolderNames = suggestionInfos; }); @@ -891,4 +915,10 @@ public class LoaderTask implements Runnable { Log.d(TAG, label); } } + + @AssistedFactory + public interface LoaderTaskFactory { + + LoaderTask newLoaderTask(BaseLauncherBinder binder, UserManagerState userState); + } } diff --git a/src/com/android/launcher3/model/ModelLauncherCallbacks.kt b/src/com/android/launcher3/model/ModelLauncherCallbacks.kt index 7ba2dad553..8b6c369e66 100644 --- a/src/com/android/launcher3/model/ModelLauncherCallbacks.kt +++ b/src/com/android/launcher3/model/ModelLauncherCallbacks.kt @@ -114,7 +114,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer override fun onUpdateSessionDisplay(key: PackageUserKey, info: SessionInfo) { /** Updates the icons and label of all pending icons for the provided package name. */ taskExecutor.accept { controller, _, _ -> - controller.app.iconCache.updateSessionCache(key, info) + controller.iconCache.updateSessionCache(key, info) } taskExecutor.accept( CacheDataUpdatedTask( @@ -128,7 +128,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer override fun onInstallSessionCreated(sessionInfo: PackageInstallInfo) { if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) { taskExecutor.accept { taskController, _, apps -> - apps.addPromiseApp(taskController.app.context, sessionInfo) + apps.addPromiseApp(taskController.context, sessionInfo) taskController.bindApplicationsIfNeeded() } } diff --git a/src/com/android/launcher3/model/ModelTaskController.kt b/src/com/android/launcher3/model/ModelTaskController.kt index 5566482738..f17ca32cce 100644 --- a/src/com/android/launcher3/model/ModelTaskController.kt +++ b/src/com/android/launcher3/model/ModelTaskController.kt @@ -16,27 +16,34 @@ package com.android.launcher3.model -import com.android.launcher3.LauncherAppState +import android.content.Context import com.android.launcher3.LauncherModel import com.android.launcher3.LauncherModel.CallbackTask import com.android.launcher3.celllayout.CellPosMapper +import com.android.launcher3.dagger.ApplicationContext +import com.android.launcher3.icons.IconCache import com.android.launcher3.model.BgDataModel.FixedContainerItems import com.android.launcher3.model.data.ItemInfo +import com.android.launcher3.util.Executors.MAIN_EXECUTOR import com.android.launcher3.util.PackageUserKey import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder import java.util.Objects -import java.util.concurrent.Executor import java.util.function.Predicate +import javax.inject.Inject /** Class with utility methods and properties for running a LauncherModel Task */ -class ModelTaskController( - val app: LauncherAppState, +class ModelTaskController +@Inject +constructor( + @ApplicationContext val context: Context, + val iconCache: IconCache, val dataModel: BgDataModel, val allAppsList: AllAppsList, - private val model: LauncherModel, - private val uiExecutor: Executor, + val model: LauncherModel, ) { + private val uiExecutor = MAIN_EXECUTOR + /** Schedules a {@param task} to be executed on the current callbacks. */ fun scheduleCallbackTask(task: CallbackTask) { for (cb in model.callbacks) { @@ -78,7 +85,7 @@ class ModelTaskController( fun bindUpdatedWidgets(dataModel: BgDataModel) { val allWidgets = - WidgetsListBaseEntriesBuilder(app.context) + WidgetsListBaseEntriesBuilder(context) .build(dataModel.widgetsModel.widgetsByPackageItemForPicker) scheduleCallbackTask { it.bindAllWidgets(allWidgets) } } diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java index a2160422b2..a3561eda4d 100644 --- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java +++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java @@ -52,11 +52,11 @@ public class PackageInstallStateChangedTask implements ModelUpdateTask { try { // For instant apps we do not get package-add. Use setting events to update // any pinned icons. - Context context = taskController.getApp().getContext(); + Context context = taskController.getContext(); ApplicationInfo ai = context .getPackageManager().getApplicationInfo(mInstallInfo.packageName, 0); if (InstantAppResolver.newInstance(context).isInstantApp(ai)) { - taskController.getApp().getModel().newModelCallbacks() + taskController.getModel().newModelCallbacks() .onPackageAdded(ai.packageName, mInstallInfo.user); } } catch (PackageManager.NameNotFoundException e) { diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index 3cdb2500e1..04f3faa194 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -38,7 +38,6 @@ import android.util.Log; import androidx.annotation.NonNull; import com.android.launcher3.Flags; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel.ModelUpdateTask; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.config.FeatureFlags; @@ -106,9 +105,8 @@ public class PackageUpdatedTask implements ModelUpdateTask { @Override public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel, @NonNull AllAppsList appsList) { - final LauncherAppState app = taskController.getApp(); - final Context context = app.getContext(); - final IconCache iconCache = app.getIconCache(); + final Context context = taskController.getContext(); + final IconCache iconCache = taskController.getIconCache(); final String[] packages = mPackages; final int packageCount = packages.length; @@ -433,7 +431,7 @@ public class PackageUpdatedTask implements ModelUpdateTask { // Load widgets for the new package. Changes due to app updates are handled through // AppWidgetHost events, this is just to initialize the long-press options. for (int i = 0; i < packageCount; i++) { - dataModel.widgetsModel.update(app, new PackageUserKey(packages[i], mUser)); + dataModel.widgetsModel.update(new PackageUserKey(packages[i], mUser)); } taskController.bindUpdatedWidgets(dataModel); } diff --git a/src/com/android/launcher3/model/SdCardAvailableReceiver.java b/src/com/android/launcher3/model/SdCardAvailableReceiver.java index 9e3f0e1aa2..9ae8092345 100644 --- a/src/com/android/launcher3/model/SdCardAvailableReceiver.java +++ b/src/com/android/launcher3/model/SdCardAvailableReceiver.java @@ -22,7 +22,6 @@ import android.content.Intent; import android.content.pm.LauncherApps; import android.os.UserHandle; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.util.ApplicationInfoWrapper; import com.android.launcher3.util.PackageUserKey; @@ -43,9 +42,10 @@ public class SdCardAvailableReceiver extends BroadcastReceiver { private final Context mContext; private final Set mPackages; - public SdCardAvailableReceiver(LauncherAppState app, Set packages) { - mModel = app.getModel(); - mContext = app.getContext(); + public SdCardAvailableReceiver( + Context context, LauncherModel model, Set packages) { + mContext = context; + mModel = model; mPackages = packages; } diff --git a/src/com/android/launcher3/model/SessionFailureTask.kt b/src/com/android/launcher3/model/SessionFailureTask.kt index 8baf568ace..6ed5178ed7 100644 --- a/src/com/android/launcher3/model/SessionFailureTask.kt +++ b/src/com/android/launcher3/model/SessionFailureTask.kt @@ -33,9 +33,9 @@ class SessionFailureTask(val packageName: String, val user: UserHandle) : ModelU dataModel: BgDataModel, apps: AllAppsList, ) { - val iconCache = taskController.app.iconCache + val iconCache = taskController.iconCache val isAppArchived = - ApplicationInfoWrapper(taskController.app.context, packageName, user).isArchived() + ApplicationInfoWrapper(taskController.context, packageName, user).isArchived() synchronized(dataModel) { if (isAppArchived) { val updatedItems = mutableListOf() diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.kt b/src/com/android/launcher3/model/ShortcutsChangedTask.kt index 56e9e43d3a..d6759e2d21 100644 --- a/src/com/android/launcher3/model/ShortcutsChangedTask.kt +++ b/src/com/android/launcher3/model/ShortcutsChangedTask.kt @@ -40,8 +40,7 @@ class ShortcutsChangedTask( dataModel: BgDataModel, apps: AllAppsList, ) { - val app = taskController.app - val context = app.context + val context = taskController.context // Find WorkspaceItemInfo's that have changed on the workspace. val matchingWorkspaceItems = ArrayList() @@ -88,7 +87,7 @@ class ShortcutsChangedTask( .filter { itemInfo: WorkspaceItemInfo -> shortcutId == itemInfo.deepShortcutId } .forEach { workspaceItemInfo: WorkspaceItemInfo -> workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context) - app.iconCache.getShortcutIcon( + taskController.iconCache.getShortcutIcon( workspaceItemInfo, CacheableShortcutInfo(fullDetails, infoWrapper), ) diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java index 3dc5ff3b57..4d28ccb42d 100644 --- a/src/com/android/launcher3/model/UserLockStateChangedTask.java +++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java @@ -23,7 +23,6 @@ import android.os.UserHandle; import androidx.annotation.NonNull; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel.ModelUpdateTask; import com.android.launcher3.LauncherSettings; import com.android.launcher3.model.data.WorkspaceItemInfo; @@ -55,8 +54,7 @@ public class UserLockStateChangedTask implements ModelUpdateTask { @Override public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel, @NonNull AllAppsList apps) { - LauncherAppState app = taskController.getApp(); - Context context = app.getContext(); + Context context = taskController.getContext(); HashMap pinnedShortcuts = new HashMap<>(); if (mIsUserUnlocked) { @@ -92,7 +90,7 @@ public class UserLockStateChangedTask implements ModelUpdateTask { } si.runtimeStatusFlags &= ~FLAG_DISABLED_LOCKED_USER; si.updateFromDeepShortcutInfo(shortcut, context); - app.getIconCache().getShortcutIcon(si, shortcut); + taskController.getIconCache().getShortcutIcon(si, shortcut); } else { si.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER; } diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java index 52b142db67..f2144c0e3a 100644 --- a/src/com/android/launcher3/model/WidgetsModel.java +++ b/src/com/android/launcher3/model/WidgetsModel.java @@ -27,6 +27,7 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dagger.ApplicationContext; import com.android.launcher3.icons.IconCache; import com.android.launcher3.icons.cache.CachedObject; import com.android.launcher3.model.data.PackageItemInfo; @@ -54,6 +55,8 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import javax.inject.Inject; + /** * Widgets data model that is used by the adapters of the widget views and controllers. * @@ -68,6 +71,29 @@ public class WidgetsModel { private final Map> mWidgetsByPackageItem = new HashMap<>(); @Nullable private WidgetValidityCheckForPicker mWidgetValidityCheckForPicker = null; + private final Context mContext; + private final InvariantDeviceProfile mIdp; + private final IconCache mIconCache; + private final AppFilter mAppFilter; + + @Inject + public WidgetsModel( + @ApplicationContext Context context, + InvariantDeviceProfile idp, + IconCache iconCache, + AppFilter appFilter) { + mContext = context; + mIdp = idp; + mIconCache = iconCache; + mAppFilter = appFilter; + } + + public WidgetsModel(Context context) { + this(context, + LauncherAppState.getIDP(context), + LauncherAppState.getInstance(context).getIconCache(), new AppFilter(context)); + } + /** * Returns all widgets keyed by their component key. */ @@ -128,36 +154,33 @@ public class WidgetsModel { * @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise * only widgets and shortcuts associated with the package/user are. */ - public List update( - LauncherAppState app, @Nullable PackageUserKey packageUser) { + public List update(@Nullable PackageUserKey packageUser) { if (!WIDGETS_ENABLED) { return new ArrayList<>(); } Preconditions.assertWorkerThread(); - Context context = app.getContext(); final ArrayList widgetsAndShortcuts = new ArrayList<>(); List updatedItems = new ArrayList<>(); try { - InvariantDeviceProfile idp = app.getInvariantDeviceProfile(); // Widgets - WidgetManagerHelper widgetManager = new WidgetManagerHelper(context); + WidgetManagerHelper widgetManager = new WidgetManagerHelper(mContext); for (AppWidgetProviderInfo widgetInfo : widgetManager.getAllProviders(packageUser)) { LauncherAppWidgetProviderInfo launcherWidgetInfo = - LauncherAppWidgetProviderInfo.fromProviderInfo(context, widgetInfo); + LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo); widgetsAndShortcuts.add(new WidgetItem( - launcherWidgetInfo, idp, app.getIconCache(), app.getContext())); + launcherWidgetInfo, mIdp, mIconCache, mContext)); updatedItems.add(launcherWidgetInfo); } // Shortcuts for (ShortcutConfigActivityInfo info : - queryList(context, packageUser)) { - widgetsAndShortcuts.add(new WidgetItem(info, app.getIconCache())); + queryList(mContext, packageUser)) { + widgetsAndShortcuts.add(new WidgetItem(info, mIconCache)); updatedItems.add(info); } - setWidgetsAndShortcuts(widgetsAndShortcuts, app, packageUser); + setWidgetsAndShortcuts(widgetsAndShortcuts, packageUser); } catch (Exception e) { if (!FeatureFlags.IS_STUDIO_BUILD && Utilities.isBinderSizeError(e)) { // the returned value may be incomplete and will not be refreshed until the next @@ -172,14 +195,14 @@ public class WidgetsModel { return updatedItems; } - private synchronized void setWidgetsAndShortcuts(ArrayList rawWidgetsShortcuts, - LauncherAppState app, @Nullable PackageUserKey packageUser) { + private synchronized void setWidgetsAndShortcuts( + ArrayList rawWidgetsShortcuts, @Nullable PackageUserKey packageUser) { if (DEBUG) { Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size()); } // Refresh the validity checker with latest app state. - mWidgetValidityCheckForPicker = new WidgetValidityCheckForPicker(app); + mWidgetValidityCheckForPicker = new WidgetValidityCheckForPicker(mIdp, mAppFilter); // Temporary cache for {@link PackageItemInfos} to avoid having to go through // {@link mPackageItemInfos} to locate the key to be used for {@link #mWidgetsList} @@ -196,19 +219,17 @@ public class WidgetsModel { // add and update. mWidgetsByPackageItem.putAll(rawWidgetsShortcuts.stream() .filter(new WidgetFlagCheck()) - .flatMap(widgetItem -> getPackageUserKeys(app.getContext(), widgetItem).stream() + .flatMap(widgetItem -> getPackageUserKeys(mContext, widgetItem).stream() .map(key -> new Pair<>(packageItemInfoCache.getOrCreate(key), widgetItem))) .collect(groupingBy(pair -> pair.first, mapping(pair -> pair.second, toList())))); // Update each package entry - IconCache iconCache = app.getIconCache(); for (PackageItemInfo p : packageItemInfoCache.values()) { - iconCache.getTitleAndIconForApp(p, DEFAULT_LOOKUP_FLAG.withUseLowRes()); + mIconCache.getTitleAndIconForApp(p, DEFAULT_LOOKUP_FLAG.withUseLowRes()); } } - public void onPackageIconsUpdated(Set packageNames, UserHandle user, - LauncherAppState app) { + public void onPackageIconsUpdated(Set packageNames, UserHandle user) { if (!WIDGETS_ENABLED) { return; } @@ -220,11 +241,10 @@ public class WidgetsModel { WidgetItem item = items.get(i); if (item.user.equals(user)) { if (item.activityInfo != null) { - items.set(i, new WidgetItem(item.activityInfo, app.getIconCache())); + items.set(i, new WidgetItem(item.activityInfo, mIconCache)); } else { - items.set(i, new WidgetItem(item.widgetInfo, - app.getInvariantDeviceProfile(), app.getIconCache(), - app.getContext())); + items.set(i, new WidgetItem( + item.widgetInfo, mIdp, mIconCache, mContext)); } } } @@ -277,9 +297,9 @@ public class WidgetsModel { private final InvariantDeviceProfile mIdp; private final AppFilter mAppFilter; - WidgetValidityCheckForPicker(LauncherAppState app) { - mIdp = app.getInvariantDeviceProfile(); - mAppFilter = new AppFilter(app.getContext()); + WidgetValidityCheckForPicker(InvariantDeviceProfile idp, AppFilter appFilter) { + mIdp = idp; + mAppFilter = appFilter; } @Override diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt index 99f2837dd0..7b8f21866a 100644 --- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt +++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt @@ -18,6 +18,7 @@ package com.android.launcher3.model import android.annotation.SuppressLint import android.appwidget.AppWidgetProviderInfo import android.content.ComponentName +import android.content.Context import android.content.Intent import android.content.pm.LauncherApps import android.content.pm.LauncherApps.ShortcutQuery @@ -29,10 +30,10 @@ import android.util.Log import android.util.LongSparseArray import com.android.launcher3.Flags import com.android.launcher3.InvariantDeviceProfile -import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings.Favorites import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError import com.android.launcher3.icons.CacheableShortcutInfo +import com.android.launcher3.icons.IconCache import com.android.launcher3.icons.cache.CacheLookupFlag.Companion.DEFAULT_LOOKUP_FLAG import com.android.launcher3.logging.FileLog import com.android.launcher3.model.data.AppInfo @@ -70,7 +71,10 @@ class WorkspaceItemProcessor( private val launcherApps: LauncherApps, private val pendingPackages: MutableSet, private val shortcutKeyToPinnedShortcuts: Map, - private val app: LauncherAppState, + private val context: Context, + private val idp: InvariantDeviceProfile, + private val iconCache: IconCache, + private val isSafeMode: Boolean, private val bgDataModel: BgDataModel, private val widgetProvidersMap: MutableMap, private val installingPkgs: HashMap, @@ -82,9 +86,7 @@ class WorkspaceItemProcessor( private val allDeepShortcuts: MutableList, ) { - private val isSafeMode = app.isSafeModeEnabled private val tempPackageKey = PackageUserKey(null, null) - private val iconCache = app.iconCache /** * This is the entry point for processing 1 workspace item. This method is like the midfielder @@ -159,7 +161,7 @@ class WorkspaceItemProcessor( ) return } - val appInfoWrapper = ApplicationInfoWrapper(app.context, targetPkg, c.user) + val appInfoWrapper = ApplicationInfoWrapper(context, targetPkg, c.user) var validTarget = launcherApps.isPackageEnabled(targetPkg, c.user) // If it's a deep shortcut, we'll use pinned shortcuts to restore it @@ -306,7 +308,7 @@ class WorkspaceItemProcessor( ) return } - info = WorkspaceItemInfo(pinnedShortcut, app.context) + info = WorkspaceItemInfo(pinnedShortcut, context) // If the pinned deep shortcut is no longer published, // use the last saved icon instead of the default. val csi = CacheableShortcutInfo(pinnedShortcut, appInfoWrapper) @@ -369,7 +371,7 @@ class WorkspaceItemProcessor( info, activityInfo, userCache.getUserInfo(c.user), - ApiWrapper.INSTANCE[app.context], + ApiWrapper.INSTANCE[context], pmHelper, ) } @@ -529,7 +531,7 @@ class WorkspaceItemProcessor( (si == null) && (lapi == null) && !(Flags.enableSupportForArchiving() && - ApplicationInfoWrapper(app.context, component.packageName, c.user) + ApplicationInfoWrapper(context, component.packageName, c.user) .isArchived()) ) { // Restore never started @@ -553,7 +555,7 @@ class WorkspaceItemProcessor( if (si == null) 0 else (si.getProgress() * 100).toInt() appWidgetInfo.pendingItemInfo = WidgetsModel.newPendingItemInfo( - app.context, + context, appWidgetInfo.providerName, appWidgetInfo.user, ) @@ -563,7 +565,7 @@ class WorkspaceItemProcessor( WidgetSizes.updateWidgetSizeRangesAsync( appWidgetInfo.appWidgetId, lapi, - app.context, + context, appWidgetInfo.spanX, appWidgetInfo.spanY, ) @@ -586,7 +588,7 @@ class WorkspaceItemProcessor( " appWidgetId: ${c.appWidgetId}," + " component=${component}", ) - logWidgetInfo(app.invariantDeviceProfile, lapi) + logWidgetInfo(idp, lapi) } } c.checkAndAddItem(appWidgetInfo, bgDataModel, memoryLogger) diff --git a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java index 1a6d1786e6..17f1615d8d 100644 --- a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java +++ b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java @@ -21,7 +21,7 @@ import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID; import android.util.LongSparseArray; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.ItemInfo; @@ -31,23 +31,37 @@ import com.android.launcher3.util.IntSet; import java.util.ArrayList; +import javax.inject.Inject; + /** * Utility class to help find space for new workspace items */ public class WorkspaceItemSpaceFinder { + private BgDataModel mDataModel; + private InvariantDeviceProfile mIDP; + private LauncherModel mModel; + + @Inject + WorkspaceItemSpaceFinder( + BgDataModel dataModel, InvariantDeviceProfile idp, LauncherModel model) { + mDataModel = dataModel; + mIDP = idp; + mModel = model; + } + /** * Find a position on the screen for the given size or adds a new screen. * * @return screenId and the coordinates for the item in an int array of size 3. */ - public int[] findSpaceForItem(LauncherAppState app, BgDataModel dataModel, + public int[] findSpaceForItem( IntArray workspaceScreens, IntArray addedWorkspaceScreensFinal, int spanX, int spanY) { LongSparseArray> screenItems = new LongSparseArray<>(); // Use sBgItemsIdMap as all the items are already loaded. - synchronized (dataModel) { - for (ItemInfo info : dataModel.itemsIdMap) { + synchronized (mDataModel) { + for (ItemInfo info : mDataModel.itemsIdMap) { if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { ArrayList items = screenItems.get(info.screenId); if (items == null) { @@ -75,7 +89,7 @@ public class WorkspaceItemSpaceFinder { for (int screen = 0; screen < screenCount; screen++) { screenId = workspaceScreens.get(screen); if (!screensToExclude.contains(screenId) && findNextAvailableIconSpaceInScreen( - app, screenItems.get(screenId), coordinates, spanX, spanY)) { + screenItems.get(screenId), coordinates, spanX, spanY)) { // We found a space for it found = true; break; @@ -84,7 +98,7 @@ public class WorkspaceItemSpaceFinder { if (!found) { // Still no position found. Add a new screen to the end. - screenId = app.getModel().getModelDbController().getNewScreenId(); + screenId = mModel.getModelDbController().getNewScreenId(); // Save the screen id for binding in the workspace workspaceScreens.add(screenId); @@ -92,7 +106,7 @@ public class WorkspaceItemSpaceFinder { // If we still can't find an empty space, then God help us all!!! if (!findNextAvailableIconSpaceInScreen( - app, screenItems.get(screenId), coordinates, spanX, spanY)) { + screenItems.get(screenId), coordinates, spanX, spanY)) { throw new RuntimeException("Can't find space to add the item"); } } @@ -100,11 +114,8 @@ public class WorkspaceItemSpaceFinder { } private boolean findNextAvailableIconSpaceInScreen( - LauncherAppState app, ArrayList occupiedPos, - int[] xy, int spanX, int spanY) { - InvariantDeviceProfile profile = app.getInvariantDeviceProfile(); - - GridOccupancy occupied = new GridOccupancy(profile.numColumns, profile.numRows); + ArrayList occupiedPos, int[] xy, int spanX, int spanY) { + GridOccupancy occupied = new GridOccupancy(mIDP.numColumns, mIDP.numRows); if (occupiedPos != null) { for (ItemInfo r : occupiedPos) { occupied.markCells(r, true); diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.kt b/src/com/android/launcher3/provider/LauncherDbUtils.kt index c92328d8a3..36413715e0 100644 --- a/src/com/android/launcher3/provider/LauncherDbUtils.kt +++ b/src/com/android/launcher3/provider/LauncherDbUtils.kt @@ -26,19 +26,17 @@ import android.os.PersistableBundle import android.os.Process import android.os.UserManager import android.text.TextUtils -import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP import com.android.launcher3.Utilities +import com.android.launcher3.dagger.LauncherComponentProvider.appComponent import com.android.launcher3.icons.IconCache -import com.android.launcher3.model.LoaderCursor import com.android.launcher3.model.UserManagerState import com.android.launcher3.pm.PinRequestHelper import com.android.launcher3.pm.UserCache import com.android.launcher3.shortcuts.ShortcutKey import com.android.launcher3.util.IntArray import com.android.launcher3.util.IntSet -import com.android.launcher3.util.PackageManagerHelper /** A set of utility methods for Launcher DB used for DB updates and migration. */ object LauncherDbUtils { @@ -155,12 +153,11 @@ object LauncherDbUtils { null, null, ) - val pmHelper = PackageManagerHelper.INSTANCE[context] val ums = UserManagerState() ums.run { init(UserCache.INSTANCE[context], context.getSystemService(UserManager::class.java)) } - val lc = LoaderCursor(c, LauncherAppState.getInstance(context), ums, pmHelper, null) + val lc = context.appComponent.loaderCursorFactory.createLoaderCursor(c, ums, null) val deletedShortcuts = IntSet() while (lc.moveToNext()) { diff --git a/src/com/android/launcher3/util/ItemInflater.kt b/src/com/android/launcher3/util/ItemInflater.kt index ebf4656c61..acb3c4ee12 100644 --- a/src/com/android/launcher3/util/ItemInflater.kt +++ b/src/com/android/launcher3/util/ItemInflater.kt @@ -24,6 +24,7 @@ import android.view.View.OnClickListener import android.view.View.OnFocusChangeListener import android.view.ViewGroup import com.android.launcher3.BubbleTextView +import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings.Favorites import com.android.launcher3.R import com.android.launcher3.apppairs.AppPairIcon @@ -46,10 +47,11 @@ class ItemInflater( private val widgetHolder: LauncherWidgetHolder, private val clickListener: OnClickListener, private val focusListener: OnFocusChangeListener, - private val defaultParent: ViewGroup + private val defaultParent: ViewGroup, ) where T : Context, T : ActivityContext { - private val widgetInflater = WidgetInflater(context) + private val widgetInflater = + WidgetInflater(context, LauncherAppState.getInstance(context).isSafeModeEnabled) @JvmOverloads fun inflateItem(item: ItemInfo, writer: ModelWriter, nullableParent: ViewGroup? = null): View? { @@ -75,7 +77,7 @@ class ItemInflater( R.layout.folder_icon, context, parent, - item as FolderInfo + item as FolderInfo, ) Favorites.ITEM_TYPE_APP_PAIR -> return AppPairIcon.inflateIcon( @@ -83,7 +85,7 @@ class ItemInflater( context, parent, item as AppPairInfo, - BubbleTextView.DISPLAY_WORKSPACE + BubbleTextView.DISPLAY_WORKSPACE, ) Favorites.ITEM_TYPE_APPWIDGET, Favorites.ITEM_TYPE_CUSTOM_APPWIDGET -> diff --git a/src/com/android/launcher3/widget/WidgetInflater.kt b/src/com/android/launcher3/widget/WidgetInflater.kt index d6cadc73a8..03f680abb4 100644 --- a/src/com/android/launcher3/widget/WidgetInflater.kt +++ b/src/com/android/launcher3/widget/WidgetInflater.kt @@ -19,14 +19,21 @@ package com.android.launcher3.widget import android.content.Context import com.android.launcher3.BuildConfig import com.android.launcher3.Launcher -import com.android.launcher3.LauncherAppState import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError +import com.android.launcher3.dagger.ApplicationContext import com.android.launcher3.logging.FileLog import com.android.launcher3.model.data.LauncherAppWidgetInfo import com.android.launcher3.qsb.QsbContainerView +import javax.inject.Inject +import javax.inject.Named /** Utility class for handling widget inflation taking into account all the restore state updates */ -class WidgetInflater(private val context: Context) { +class WidgetInflater +@Inject +constructor( + @ApplicationContext private val context: Context, + @Named("SAFE_MODE") private val isSafeModeEnabled: Boolean, +) { private val widgetHelper = WidgetManagerHelper(context) @@ -41,9 +48,8 @@ class WidgetInflater(private val context: Context) { ) } } - if (LauncherAppState.INSTANCE.get(context).isSafeModeEnabled) { - return InflationResult(TYPE_PENDING) - } + if (isSafeModeEnabled) return InflationResult(TYPE_PENDING) + val appWidgetInfo: LauncherAppWidgetProviderInfo? var removalReason = "" @RestoreError var logReason = RestoreError.OTHER_WIDGET_INFLATION_FAIL diff --git a/tests/multivalentTests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt index 08b8f81c11..25f4cf15dc 100644 --- a/tests/multivalentTests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt @@ -33,7 +33,6 @@ import org.mockito.Mockito.times import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.mock -import org.mockito.kotlin.same import org.mockito.kotlin.verify import org.mockito.kotlin.verifyNoMoreInteractions import org.mockito.kotlin.whenever @@ -142,10 +141,9 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() { /** Sets up the item space data that will be returned from WorkspaceItemSpaceFinder. */ private fun givenNewItemSpaces(vararg newItemSpaces: NewItemSpace) { val spaceStack = newItemSpaces.toMutableList() - whenever( - mWorkspaceItemSpaceFinder.findSpaceForItem(any(), any(), any(), any(), any(), any()) - ) - .then { spaceStack.removeFirst().toIntArray() } + whenever(mWorkspaceItemSpaceFinder.findSpaceForItem(any(), any(), any(), any())).then { + spaceStack.removeFirst().toIntArray() + } } /** @@ -155,8 +153,6 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() { private fun verifyItemSpaceFinderCall(nonEmptyScreenIds: List, numberOfExpectedCall: Int) { verify(mWorkspaceItemSpaceFinder, times(numberOfExpectedCall)) .findSpaceForItem( - eq(mAppState), - same(mModelHelper.bgDataModel), eq(IntArray.wrap(*nonEmptyScreenIds.toIntArray())), eq(IntArray()), eq(1), diff --git a/tests/multivalentTests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/multivalentTests/src/com/android/launcher3/model/LoaderCursorTest.java index ad408185b2..b848d27cd9 100644 --- a/tests/multivalentTests/src/com/android/launcher3/model/LoaderCursorTest.java +++ b/tests/multivalentTests/src/com/android/launcher3/model/LoaderCursorTest.java @@ -55,7 +55,6 @@ import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.database.MatrixCursor; import android.graphics.Bitmap; @@ -76,6 +75,7 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.util.Executors; import com.android.launcher3.util.LauncherModelHelper; +import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext; import com.android.launcher3.util.PackageManagerHelper; import org.junit.After; @@ -96,11 +96,10 @@ public class LoaderCursorTest { private LauncherModelHelper mModelHelper; private LauncherAppState mApp; - private PackageManagerHelper mPmHelper; private MatrixCursor mCursor; private InvariantDeviceProfile mIDP; - private Context mContext; + private SandboxModelContext mContext; private LoaderCursor mLoaderCursor; @@ -116,7 +115,6 @@ public class LoaderCursorTest { mContext = mModelHelper.sandboxContext; mIDP = InvariantDeviceProfile.INSTANCE.get(mContext); mApp = LauncherAppState.getInstance(mContext); - mPmHelper = PackageManagerHelper.INSTANCE.get(mContext); mCursor = new MatrixCursor(new String[] { ICON, TITLE, _ID, CONTAINER, ITEM_TYPE, @@ -126,7 +124,8 @@ public class LoaderCursorTest { }); UserManagerState ums = new UserManagerState(); - mLoaderCursor = new LoaderCursor(mCursor, mApp, ums, mPmHelper, null); + mLoaderCursor = mContext.getAppComponent().getLoaderCursorFactory() + .createLoaderCursor(mCursor, ums, null); ums.allUsers.put(0, Process.myUserHandle()); } diff --git a/tests/multivalentTests/src/com/android/launcher3/model/PackageUpdatedTaskTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/PackageUpdatedTaskTest.kt index eec6eeddd0..5fd93d13ce 100644 --- a/tests/multivalentTests/src/com/android/launcher3/model/PackageUpdatedTaskTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/model/PackageUpdatedTaskTest.kt @@ -27,8 +27,9 @@ import android.platform.test.flag.junit.SetFlagsRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.launcher3.AppFilter import com.android.launcher3.Flags.FLAG_ENABLE_PRIVATE_SPACE -import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings +import com.android.launcher3.dagger.LauncherAppComponent +import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.icons.IconCache import com.android.launcher3.model.PackageUpdatedTask.OP_ADD import com.android.launcher3.model.PackageUpdatedTask.OP_REMOVE @@ -39,17 +40,20 @@ import com.android.launcher3.model.PackageUpdatedTask.OP_UPDATE import com.android.launcher3.model.PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE import com.android.launcher3.model.data.AppInfo import com.android.launcher3.model.data.WorkspaceItemInfo +import com.android.launcher3.util.AllModulesForTest import com.android.launcher3.util.Executors import com.android.launcher3.util.LauncherModelHelper -import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext import com.android.launcher3.util.TestUtil import com.google.common.truth.Truth.assertThat +import dagger.BindsInstance +import dagger.Component import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any +import org.mockito.kotlin.doAnswer import org.mockito.kotlin.mock import org.mockito.kotlin.spy import org.mockito.kotlin.verify @@ -61,10 +65,8 @@ class PackageUpdatedTaskTest { @get:Rule val setFlagsRule = SetFlagsRule() private val mUser = myUserHandle() - private val mDataModel: BgDataModel = BgDataModel() private val mLauncherModelHelper = LauncherModelHelper() - private val mContext: SandboxModelContext = spy(mLauncherModelHelper.sandboxContext) - private val mAppState: LauncherAppState = spy(LauncherAppState.getInstance(mContext)) + private val mContext = mLauncherModelHelper.sandboxContext private val expectedPackage = "Test.Package" private val expectedComponent = ComponentName(expectedPackage, "TestClass") @@ -72,22 +74,33 @@ class PackageUpdatedTaskTest { private val expectedWorkspaceItem = spy(WorkspaceItemInfo()) private val mockIconCache: IconCache = mock() - private val mockTaskController: ModelTaskController = mock() private val mockAppFilter: AppFilter = mock() + private lateinit var mAllAppsList: AllAppsList + private val mockApplicationInfo: ApplicationInfo = mock() private val mockActivityInfo: ActivityInfo = mock() - private lateinit var mAllAppsList: AllAppsList + private lateinit var mDataModel: BgDataModel + private lateinit var mockTaskController: ModelTaskController @Before fun setup() { mAllAppsList = spy(AllAppsList(mockIconCache, mockAppFilter)) - mLauncherModelHelper.sandboxContext.spyService(LauncherApps::class.java).apply { + mContext.initDaggerComponent( + DaggerPackageUpdatedTaskTest_TestComponent.builder() + .bindAllAppsList(mAllAppsList) + .bindAppFilter(mockAppFilter) + .bindIconCache(mockIconCache) + ) + + mContext.spyService(LauncherApps::class.java).apply { whenever(getActivityList(expectedPackage, mUser)) .thenReturn(listOf(expectedActivityInfo)) } - whenever(mAppState.iconCache).thenReturn(mockIconCache) - whenever(mockTaskController.app).thenReturn(mAppState) + + mockTaskController = spy((mContext.appComponent as TestComponent).getTaskController()) + mDataModel = (mContext.appComponent as TestComponent).getDataModel() + whenever(mockAppFilter.shouldShowApp(expectedComponent)).thenReturn(true) mockApplicationInfo.apply { uid = 1 @@ -122,7 +135,6 @@ class PackageUpdatedTaskTest { TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { taskUnderTest.execute(mockTaskController, mDataModel, mAllAppsList) } - mLauncherModelHelper.loadModelSync() // Then verify(mockIconCache).updateIconsForPkg(expectedPackage, mUser) verify(mAllAppsList).addPackage(mContext, expectedPackage, mUser) @@ -141,7 +153,6 @@ class PackageUpdatedTaskTest { TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { taskUnderTest.execute(mockTaskController, mDataModel, mAllAppsList) } - mLauncherModelHelper.loadModelSync() // Then verify(mockIconCache).updateIconsForPkg(expectedPackage, mUser) verify(mAllAppsList).updatePackage(mContext, expectedPackage, mUser) @@ -159,7 +170,6 @@ class PackageUpdatedTaskTest { TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { taskUnderTest.execute(mockTaskController, mDataModel, mAllAppsList) } - mLauncherModelHelper.loadModelSync() // Then verify(mockIconCache).removeIconsForPkg(expectedPackage, mUser) verify(mAllAppsList).removePackage(expectedPackage, mUser) @@ -176,7 +186,6 @@ class PackageUpdatedTaskTest { TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { taskUnderTest.execute(mockTaskController, mDataModel, mAllAppsList) } - mLauncherModelHelper.loadModelSync() // Then verify(mAllAppsList).removePackage(expectedPackage, mUser) verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWorkspaceItem)) @@ -190,10 +199,11 @@ class PackageUpdatedTaskTest { // When mDataModel.addItem(mContext, expectedWorkspaceItem, true) mAllAppsList.add(AppInfo(mContext, expectedActivityInfo, mUser), expectedActivityInfo) + mAllAppsList.getAndResetChangeFlag() + doAnswer {}.whenever(mockTaskController).bindApplicationsIfNeeded() TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { taskUnderTest.execute(mockTaskController, mDataModel, mAllAppsList) } - mLauncherModelHelper.loadModelSync() // Then verify(mAllAppsList).updateDisabledFlags(any(), any()) verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWorkspaceItem)) @@ -206,10 +216,11 @@ class PackageUpdatedTaskTest { val taskUnderTest = PackageUpdatedTask(OP_UNSUSPEND, mUser, expectedPackage) // When mDataModel.addItem(mContext, expectedWorkspaceItem, true) + mAllAppsList.getAndResetChangeFlag() + doAnswer {}.whenever(mockTaskController).bindApplicationsIfNeeded() TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { taskUnderTest.execute(mockTaskController, mDataModel, mAllAppsList) } - mLauncherModelHelper.loadModelSync() // Then verify(mAllAppsList).updateDisabledFlags(any(), any()) verify(mockTaskController).bindUpdatedWorkspaceItems(emptyList()) @@ -226,10 +237,29 @@ class PackageUpdatedTaskTest { TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { taskUnderTest.execute(mockTaskController, mDataModel, mAllAppsList) } - mLauncherModelHelper.loadModelSync() // Then verify(mAllAppsList).updateDisabledFlags(any(), any()) verify(mockTaskController).bindUpdatedWorkspaceItems(emptyList()) assertThat(mAllAppsList.data).isEmpty() } + + @LauncherAppSingleton + @Component(modules = [AllModulesForTest::class]) + interface TestComponent : LauncherAppComponent { + + fun getDataModel(): BgDataModel + + fun getTaskController(): ModelTaskController + + @Component.Builder + interface Builder : LauncherAppComponent.Builder { + @BindsInstance fun bindAppFilter(appFilter: AppFilter): Builder + + @BindsInstance fun bindIconCache(iconCache: IconCache): Builder + + @BindsInstance fun bindAllAppsList(list: AllAppsList): Builder + + override fun build(): TestComponent + } + } } diff --git a/tests/multivalentTests/src/com/android/launcher3/model/ShortcutsChangedTaskTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/ShortcutsChangedTaskTest.kt index c6863f40f1..0ab736b26c 100644 --- a/tests/multivalentTests/src/com/android/launcher3/model/ShortcutsChangedTaskTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/model/ShortcutsChangedTaskTest.kt @@ -30,7 +30,6 @@ import android.platform.test.flag.junit.SetFlagsRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.launcher3.Flags -import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT import com.android.launcher3.icons.BitmapInfo import com.android.launcher3.icons.CacheableShortcutInfo @@ -73,7 +72,6 @@ class ShortcutsChangedTaskTest { private val user: UserHandle = myUserHandle() private val mockTaskController: ModelTaskController = mock() private val mockAllApps: AllAppsList = mock() - private val mockAppState: LauncherAppState = mock() private val mockIconCache: IconCache = mock() private val expectedWai = @@ -93,9 +91,8 @@ class ShortcutsChangedTaskTest { modelHelper.loadModelSync() context = modelHelper.sandboxContext launcherApps = context.spyService(LauncherApps::class.java) - whenever(mockTaskController.app).thenReturn(mockAppState) - whenever(mockAppState.context).thenReturn(context) - whenever(mockAppState.iconCache).thenReturn(mockIconCache) + whenever(mockTaskController.context).thenReturn(context) + whenever(mockTaskController.iconCache).thenReturn(mockIconCache) whenever(mockIconCache.getShortcutIcon(eq(expectedWai), any())) .then { _ -> { expectedWai.bitmap = BitmapInfo.LOW_RES_INFO } } shortcuts = emptyList() @@ -132,8 +129,7 @@ class ShortcutsChangedTaskTest { // When shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps) // Then - verify(mockAppState.iconCache) - .getShortcutIcon(eq(expectedWai), any()) + verify(mockIconCache).getShortcutIcon(eq(expectedWai), any()) verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWai)) } @@ -196,8 +192,7 @@ class ShortcutsChangedTaskTest { // When shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps) // Then - verify(mockAppState.iconCache) - .getShortcutIcon(eq(expectedWai), any()) + verify(mockIconCache).getShortcutIcon(eq(expectedWai), any()) verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWai)) } @@ -256,8 +251,7 @@ class ShortcutsChangedTaskTest { // When shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps) // Then - verify(mockAppState.iconCache) - .getShortcutIcon(eq(expectedWai), any()) + verify(mockIconCache).getShortcutIcon(eq(expectedWai), any()) verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWai)) } @@ -287,8 +281,7 @@ class ShortcutsChangedTaskTest { // When shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps) // Then - verify(mockAppState.iconCache) - .getShortcutIcon(eq(expectedWai), any()) + verify(mockIconCache).getShortcutIcon(eq(expectedWai), any()) verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWai)) } diff --git a/tests/multivalentTests/src/com/android/launcher3/model/WidgetsModelTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/WidgetsModelTest.kt index 777d81babe..2e6ecc5d94 100644 --- a/tests/multivalentTests/src/com/android/launcher3/model/WidgetsModelTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/model/WidgetsModelTest.kt @@ -25,9 +25,9 @@ import android.platform.test.rule.DeviceProduct import android.platform.test.rule.LimitDevicesRule import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.launcher3.AppFilter import com.android.launcher3.DeviceProfile import com.android.launcher3.InvariantDeviceProfile -import com.android.launcher3.LauncherAppState import com.android.launcher3.icons.IconCache import com.android.launcher3.model.data.PackageItemInfo import com.android.launcher3.pm.UserCache @@ -62,7 +62,6 @@ class WidgetsModelTest { @Rule @JvmField val mockitoRule: MockitoRule = MockitoJUnit.rule() @Mock private lateinit var appWidgetManager: AppWidgetManager - @Mock private lateinit var app: LauncherAppState @Mock private lateinit var iconCacheMock: IconCache private lateinit var context: Context @@ -93,9 +92,6 @@ class WidgetsModelTest { whenever(iconCacheMock.getTitleNoCache(any())) .thenReturn("title") - whenever(app.iconCache).thenReturn(iconCacheMock) - whenever(app.context).thenReturn(context) - whenever(app.invariantDeviceProfile).thenReturn(idp) val widgetToCategoryEntry: Map.Entry = WidgetSections.getWidgetsToCategory(context).entries.first() @@ -128,7 +124,7 @@ class WidgetsModelTest { val userCache = spy(UserCache.INSTANCE.get(context)) whenever(userCache.userProfiles).thenReturn(listOf(UserHandle.CURRENT)) - underTest = WidgetsModel() + underTest = WidgetsModel(context, idp, iconCacheMock, AppFilter(context)) } @Test @@ -237,7 +233,7 @@ class WidgetsModelTest { update = false // Similarly, model could update its code independently while a client is // iterating on the list. - underTest.update(app, /* packageUser= */ null) + underTest.update(/* packageUser= */ null) } } @@ -253,7 +249,7 @@ class WidgetsModelTest { private fun loadWidgets() { val latch = CountDownLatch(1) Executors.MODEL_EXECUTOR.execute { - underTest.update(app, /* packageUser= */ null) + underTest.update(/* packageUser= */ null) latch.countDown() } if (!latch.await(LOAD_WIDGETS_TIMEOUT_SECONDS, TimeUnit.SECONDS)) { diff --git a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt index a55d64ba4f..cba7b88890 100644 --- a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt @@ -31,7 +31,7 @@ import android.platform.test.flag.junit.SetFlagsRule import android.util.LongSparseArray import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.launcher3.Flags -import com.android.launcher3.LauncherAppState +import com.android.launcher3.InvariantDeviceProfile import com.android.launcher3.LauncherSettings.Favorites import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION @@ -41,6 +41,7 @@ import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER import com.android.launcher3.Utilities.EMPTY_PERSON_ARRAY import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError import com.android.launcher3.icons.CacheableShortcutInfo +import com.android.launcher3.icons.IconCache import com.android.launcher3.model.data.FolderInfo import com.android.launcher3.model.data.IconRequestInfo import com.android.launcher3.model.data.ItemInfo @@ -66,12 +67,14 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Answers import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.RETURNS_DEEP_STUBS import org.mockito.Mockito.mock import org.mockito.Mockito.times import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.doAnswer @@ -88,12 +91,12 @@ class WorkspaceItemProcessorTest { @Mock private lateinit var mockIconRequestInfo: IconRequestInfo @Mock private lateinit var mockWorkspaceInfo: WorkspaceItemInfo @Mock private lateinit var mockBgDataModel: BgDataModel - @Mock private lateinit var mockAppState: LauncherAppState @Mock private lateinit var mockPmHelper: PackageManagerHelper - @Mock private lateinit var mockCursor: LoaderCursor + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var mockCursor: LoaderCursor @Mock private lateinit var mockUserCache: UserCache @Mock private lateinit var mockUserManagerState: UserManagerState @Mock private lateinit var mockWidgetInflater: WidgetInflater + @Mock private lateinit var mockIconCache: IconCache lateinit var mModelHelper: LauncherModelHelper lateinit var mContext: SandboxModelContext @@ -114,6 +117,7 @@ class WorkspaceItemProcessorTest { @Before fun setup() { + MockitoAnnotations.initMocks(this) mModelHelper = LauncherModelHelper() mContext = mModelHelper.sandboxContext mLauncherApps = @@ -122,9 +126,6 @@ class WorkspaceItemProcessorTest { doReturn(true).whenever(this).isActivityEnabled(mComponentName, mUserHandle) } mUserHandle = Process.myUserHandle() - mockIconRequestInfo = mock>() - mockWorkspaceInfo = mock() - mockBgDataModel = mock() mComponentName = ComponentName("package", "class") mUnlockedUsersArray = LongSparseArray(1).apply { put(101, true) } mIntent = @@ -133,40 +134,26 @@ class WorkspaceItemProcessorTest { `package` = "pkg" putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "") } - mockAppState = - mock().apply { - whenever(context).thenReturn(mContext) - whenever(iconCache).thenReturn(mock()) - whenever(iconCache.getShortcutIcon(any(), any(), any())).then {} - } - mockPmHelper = - mock().apply { - whenever(getAppLaunchIntent(mComponentName.packageName, mUserHandle)) - .thenReturn(mIntent) - } - mockCursor = - mock(LoaderCursor::class.java, RETURNS_DEEP_STUBS).apply { - user = mUserHandle - itemType = ITEM_TYPE_APPLICATION - id = 1 - restoreFlag = 1 - serialNumber = 101 - whenever(parseIntent()).thenReturn(mIntent) - whenever(markRestored()).doAnswer { restoreFlag = 0 } - whenever(updater().put(Favorites.INTENT, mIntent.toUri(0)).commit()).thenReturn(1) - whenever(getAppShortcutInfo(any(), any(), any(), any())) - .thenReturn(mockWorkspaceInfo) - whenever(createIconRequestInfo(any(), any())).thenReturn(mockIconRequestInfo) - } - mockUserCache = - mock().apply { - val userIconInfo = - mock().apply { whenever(isPrivate).thenReturn(false) } - whenever(getUserInfo(any())).thenReturn(userIconInfo) - } + whenever(mockIconCache.getShortcutIcon(any(), any(), any())).then {} + whenever(mockPmHelper.getAppLaunchIntent(mComponentName.packageName, mUserHandle)) + .thenReturn(mIntent) + mockCursor.apply { + user = mUserHandle + itemType = ITEM_TYPE_APPLICATION + id = 1 + restoreFlag = 1 + serialNumber = 101 + whenever(parseIntent()).thenReturn(mIntent) + whenever(markRestored()).doAnswer { restoreFlag = 0 } + whenever(updater().put(Favorites.INTENT, mIntent.toUri(0)).commit()).thenReturn(1) + whenever(getAppShortcutInfo(any(), any(), any(), any())).thenReturn(mockWorkspaceInfo) + whenever(createIconRequestInfo(any(), any())).thenReturn(mockIconRequestInfo) + } + mockUserCache.apply { + val userIconInfo = mock().apply { whenever(isPrivate).thenReturn(false) } + whenever(getUserInfo(any())).thenReturn(userIconInfo) + } - mockUserManagerState = mock() - mockWidgetInflater = mock() mKeyToPinnedShortcutsMap = mutableMapOf() mInstallingPkgs = hashMapOf() mAllDeepShortcuts = mutableListOf() @@ -187,7 +174,6 @@ class WorkspaceItemProcessorTest { userManagerState: UserManagerState = mockUserManagerState, launcherApps: LauncherApps = mLauncherApps, shortcutKeyToPinnedShortcuts: Map = mKeyToPinnedShortcutsMap, - app: LauncherAppState = mockAppState, bgDataModel: BgDataModel = mockBgDataModel, widgetProvidersMap: MutableMap = mWidgetProvidersMap, widgetInflater: WidgetInflater = mockWidgetInflater, @@ -205,7 +191,7 @@ class WorkspaceItemProcessorTest { userCache = userCache, userManagerState = userManagerState, launcherApps = launcherApps, - app = app, + context = mContext, bgDataModel = bgDataModel, widgetProvidersMap = widgetProvidersMap, widgetInflater = widgetInflater, @@ -217,6 +203,9 @@ class WorkspaceItemProcessorTest { shortcutKeyToPinnedShortcuts = shortcutKeyToPinnedShortcuts, installingPkgs = installingPkgs, allDeepShortcuts = allDeepShortcuts, + iconCache = mockIconCache, + idp = InvariantDeviceProfile.INSTANCE.get(mContext), + isSafeMode = false, ) @Test diff --git a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt index dd03eee12c..a18f93b9dc 100644 --- a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt @@ -29,8 +29,6 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() { - private val mItemSpaceFinder = WorkspaceItemSpaceFinder() - @Before override fun setup() { super.setup() @@ -42,15 +40,12 @@ class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() { } private fun findSpace(spanX: Int, spanY: Int): NewItemSpace = - mItemSpaceFinder - .findSpaceForItem( - mAppState, + WorkspaceItemSpaceFinder( mModelHelper.bgDataModel, - mExistingScreens, - mNewScreens, - spanX, - spanY, + mAppState.invariantDeviceProfile, + mModelHelper.model, ) + .findSpaceForItem(mExistingScreens, mNewScreens, spanX, spanY) .let { NewItemSpace.fromIntArray(it) } private fun assertRegionVacant(newItemSpace: NewItemSpace, spanX: Int, spanY: Int) { diff --git a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt index 246219ffda..7f9b7a0ecb 100644 --- a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt +++ b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt @@ -16,7 +16,6 @@ import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito import com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn import com.android.launcher3.Flags -import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherModel import com.android.launcher3.LauncherModel.LoaderTransaction import com.android.launcher3.LauncherPrefs @@ -31,6 +30,7 @@ import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.icons.IconCache import com.android.launcher3.icons.cache.CachingLogic import com.android.launcher3.icons.cache.IconCacheUpdateHandler +import com.android.launcher3.model.LoaderTask.LoaderTaskFactory import com.android.launcher3.model.data.AppInfo import com.android.launcher3.model.data.IconRequestInfo import com.android.launcher3.model.data.WorkspaceItemInfo @@ -43,7 +43,6 @@ import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext import com.android.launcher3.util.LooperIdleLock import com.android.launcher3.util.TestUtil import com.android.launcher3.util.UserIconInfo -import com.google.common.truth.Truth import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component @@ -57,7 +56,6 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito -import org.mockito.Mockito.mock import org.mockito.Mockito.times import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @@ -93,26 +91,28 @@ class LoaderTaskTest { @Mock private lateinit var bgAllAppsList: AllAppsList @Mock private lateinit var modelDelegate: ModelDelegate - @Mock private lateinit var launcherBinder: BaseLauncherBinder - private lateinit var launcherModel: LauncherModel - @Mock private lateinit var transaction: LoaderTransaction + @Mock private lateinit var launcherModel: LauncherModel @Mock private lateinit var iconCache: IconCache - @Mock private lateinit var idleLock: LooperIdleLock - @Mock private lateinit var iconCacheUpdateHandler: IconCacheUpdateHandler @Mock private lateinit var userCache: UserCache - @Spy private var userManagerState: UserManagerState? = UserManagerState() + @Mock private lateinit var launcherBinder: BaseLauncherBinder + @Mock private lateinit var transaction: LoaderTransaction + @Mock private lateinit var idleLock: LooperIdleLock + @Mock private lateinit var iconCacheUpdateHandler: IconCacheUpdateHandler + + @Spy private var userManagerState: UserManagerState = UserManagerState() @get:Rule val setFlagsRule = SetFlagsRule() - private val app: LauncherAppState - get() = context.appComponent.launcherAppState + private val testComponent: TestComponent + get() = context.appComponent as TestComponent + + private val bgDataModel: BgDataModel + get() = testComponent.getDataModel() @Before fun setup() { MockitoAnnotations.initMocks(this) - setFlagsRule.enableFlags(Flags.FLAG_ENABLE_TIERED_WIDGETS_BY_DEFAULT_IN_PICKER) - launcherModel = mock(LauncherModel::class.java) mockitoSession = ExtendedMockito.mockitoSession() .strictness(Strictness.LENIENT) @@ -125,14 +125,17 @@ class LoaderTaskTest { `when`(launcherModel.beginLoader(any())).thenReturn(transaction) `when`(launcherModel.modelDbController) .thenReturn(FactitiousDbController(context, INSERTION_STATEMENT_FILE)) + `when`(launcherModel.modelDelegate).thenReturn(modelDelegate) `when`(launcherBinder.newIdleLock(any())).thenReturn(idleLock) `when`(idleLock.awaitLocked(1000)).thenReturn(false) `when`(iconCache.getUpdateHandler()).thenReturn(iconCacheUpdateHandler) + context.initDaggerComponent( DaggerLoaderTaskTest_TestComponent.builder() .bindUserCache(userCache) .bindIconCache(iconCache) .bindLauncherModel(launcherModel) + .bindAllAppsList(bgAllAppsList) ) context.appComponent.idp.apply { numRows = 5 @@ -152,14 +155,16 @@ class LoaderTaskTest { @Test fun loadsDataProperly() = - with(BgDataModel()) { + with(bgDataModel) { val MAIN_HANDLE = Process.myUserHandle() val mockUserHandles = arrayListOf(MAIN_HANDLE) `when`(userCache.userProfiles).thenReturn(mockUserHandles) `when`(userCache.getUserInfo(MAIN_HANDLE)).thenReturn(UserIconInfo(MAIN_HANDLE, 1)) - LoaderTask(app, bgAllAppsList, this, modelDelegate, launcherBinder) + testComponent + .getLoaderTaskFactory() + .newLoaderTask(launcherBinder, userManagerState) .runSyncOnBackgroundThread() - Truth.assertThat( + assertThat( itemsIdMap .filter { it.container == CONTAINER_DESKTOP || it.container == CONTAINER_HOTSEAT @@ -167,9 +172,8 @@ class LoaderTaskTest { .size ) .isAtLeast(32) - Truth.assertThat(itemsIdMap.filter { ModelUtils.WIDGET_FILTER.test(it) }.size) - .isAtLeast(7) - Truth.assertThat( + assertThat(itemsIdMap.filter { ModelUtils.WIDGET_FILTER.test(it) }.size).isAtLeast(7) + assertThat( itemsIdMap .filter { it.itemType == ITEM_TYPE_FOLDER || it.itemType == ITEM_TYPE_APP_PAIR @@ -177,12 +181,14 @@ class LoaderTaskTest { .size ) .isAtLeast(8) - Truth.assertThat(itemsIdMap.size()).isAtLeast(40) + assertThat(itemsIdMap.size()).isAtLeast(40) } @Test fun bindsLoadedDataCorrectly() { - LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + testComponent + .getLoaderTaskFactory() + .newLoaderTask(launcherBinder, userManagerState) .runSyncOnBackgroundThread() verify(launcherBinder).bindWorkspace(true, false) @@ -200,7 +206,7 @@ class LoaderTaskTest { @Test fun setsQuietModeFlagCorrectlyForWorkProfile() = - with(BgDataModel()) { + with(bgDataModel) { setFlagsRule.enableFlags(Flags.FLAG_ENABLE_PRIVATE_SPACE) val MAIN_HANDLE = Process.myUserHandle() val mockUserHandles = arrayListOf(MAIN_HANDLE) @@ -208,7 +214,9 @@ class LoaderTaskTest { `when`(userManagerState?.isUserQuiet(MAIN_HANDLE)).thenReturn(true) `when`(userCache.getUserInfo(MAIN_HANDLE)).thenReturn(UserIconInfo(MAIN_HANDLE, 1)) - LoaderTask(app, bgAllAppsList, this, modelDelegate, launcherBinder, userManagerState) + testComponent + .getLoaderTaskFactory() + .newLoaderTask(launcherBinder, userManagerState) .runSyncOnBackgroundThread() verify(bgAllAppsList) @@ -221,7 +229,7 @@ class LoaderTaskTest { @Test fun setsQuietModeFlagCorrectlyForPrivateProfile() = - with(BgDataModel()) { + with(bgDataModel) { setFlagsRule.enableFlags(Flags.FLAG_ENABLE_PRIVATE_SPACE) val MAIN_HANDLE = Process.myUserHandle() val mockUserHandles = arrayListOf(MAIN_HANDLE) @@ -229,7 +237,9 @@ class LoaderTaskTest { `when`(userManagerState?.isUserQuiet(MAIN_HANDLE)).thenReturn(true) `when`(userCache.getUserInfo(MAIN_HANDLE)).thenReturn(UserIconInfo(MAIN_HANDLE, 3)) - LoaderTask(app, bgAllAppsList, this, modelDelegate, launcherBinder, userManagerState) + testComponent + .getLoaderTaskFactory() + .newLoaderTask(launcherBinder, userManagerState) .runSyncOnBackgroundThread() verify(bgAllAppsList) @@ -268,7 +278,9 @@ class LoaderTaskTest { RestoreDbTask.setPending(spyContext) // When - LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + testComponent + .getLoaderTaskFactory() + .newLoaderTask(launcherBinder, userManagerState) .runSyncOnBackgroundThread() // Then @@ -336,7 +348,9 @@ class LoaderTaskTest { Settings.Secure.putInt(spyContext.contentResolver, "launcher_broadcast_installed_apps", 0) // When - LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + testComponent + .getLoaderTaskFactory() + .newLoaderTask(launcherBinder, userManagerState) .runSyncOnBackgroundThread() // Then @@ -375,7 +389,9 @@ class LoaderTaskTest { RestoreDbTask.setPending(spyContext) // When - LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + testComponent + .getLoaderTaskFactory() + .newLoaderTask(launcherBinder, userManagerState) .runSyncOnBackgroundThread() // Then @@ -414,7 +430,9 @@ class LoaderTaskTest { RestoreDbTask.setPending(spyContext) // When - LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + testComponent + .getLoaderTaskFactory() + .newLoaderTask(launcherBinder, userManagerState) .runSyncOnBackgroundThread() // Then @@ -444,7 +462,8 @@ class LoaderTaskTest { ) val expectedAppInfo = AppInfo().apply { componentName = expectedComponent } // When - val loader = LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + val loader = + testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState) val actualIconRequest = loader.getAppInfoIconRequestInfo(expectedAppInfo, activityInfo, workspaceIconRequests) // Then @@ -474,7 +493,8 @@ class LoaderTaskTest { ) val expectedAppInfo = AppInfo().apply { componentName = expectedComponent } // When - val loader = LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + val loader = + testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState) val actualIconRequest = loader.getAppInfoIconRequestInfo(expectedAppInfo, activityInfo, workspaceIconRequests) // Then @@ -505,7 +525,8 @@ class LoaderTaskTest { val expectedAppInfo = AppInfo().apply { componentName = ComponentName("differentPkg", "differentClass") } // When - val loader = LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + val loader = + testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState) val actualIconRequest = loader.getAppInfoIconRequestInfo(expectedAppInfo, activityInfo, workspaceIconRequests) // Then @@ -532,7 +553,8 @@ class LoaderTaskTest { ) val expectedAppInfo = AppInfo() // When - val loader = LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder) + val loader = + testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState) val actualIconRequest = loader.getAppInfoIconRequestInfo(expectedAppInfo, activityInfo, workspaceIconRequests) // Then @@ -543,6 +565,11 @@ class LoaderTaskTest { @LauncherAppSingleton @Component(modules = [AllModulesForTest::class]) interface TestComponent : LauncherAppComponent { + + fun getLoaderTaskFactory(): LoaderTaskFactory + + fun getDataModel(): BgDataModel + @Component.Builder interface Builder : LauncherAppComponent.Builder { @BindsInstance fun bindUserCache(userCache: UserCache): Builder @@ -551,6 +578,8 @@ class LoaderTaskTest { @BindsInstance fun bindIconCache(iconCache: IconCache): Builder + @BindsInstance fun bindAllAppsList(list: AllAppsList): Builder + override fun build(): TestComponent } } diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt index 8db049c492..fd44023de4 100644 --- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt +++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt @@ -30,12 +30,13 @@ import android.util.LongSparseArray import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.launcher3.Flags.FLAG_ENABLE_SUPPORT_FOR_ARCHIVING -import com.android.launcher3.LauncherAppState +import com.android.launcher3.InvariantDeviceProfile import com.android.launcher3.LauncherSettings.Favorites import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET import com.android.launcher3.icons.CacheableShortcutInfo +import com.android.launcher3.icons.IconCache import com.android.launcher3.model.data.IconRequestInfo import com.android.launcher3.model.data.LauncherAppWidgetInfo import com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_RESTORE_STARTED @@ -52,11 +53,12 @@ import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Answers import org.mockito.ArgumentCaptor import org.mockito.Mock -import org.mockito.Mockito import org.mockito.Mockito.RETURNS_DEEP_STUBS import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.doAnswer @@ -71,10 +73,10 @@ class WorkspaceItemProcessorExtraTest { @Mock private lateinit var mockWorkspaceInfo: WorkspaceItemInfo @Mock private lateinit var mockBgDataModel: BgDataModel @Mock private lateinit var mockContext: Context - @Mock private lateinit var mockAppState: LauncherAppState + @Mock private lateinit var mockIconCache: IconCache @Mock private lateinit var mockPmHelper: PackageManagerHelper @Mock private lateinit var mockLauncherApps: LauncherApps - @Mock private lateinit var mockCursor: LoaderCursor + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var mockCursor: LoaderCursor @Mock private lateinit var mockUserCache: UserCache @Mock private lateinit var mockUserManagerState: UserManagerState @Mock private lateinit var mockWidgetInflater: WidgetInflater @@ -95,10 +97,9 @@ class WorkspaceItemProcessorExtraTest { @Before fun setup() { + MockitoAnnotations.initMocks(this) + mUserHandle = UserHandle(0) - mockIconRequestInfo = mock>() - mockWorkspaceInfo = mock() - mockBgDataModel = mock() mComponentName = ComponentName("package", "class") mUnlockedUsersArray = LongSparseArray(1).apply { put(101, true) } intent = @@ -107,52 +108,36 @@ class WorkspaceItemProcessorExtraTest { `package` = "pkg" putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "") } - mockLauncherApps = - mock().apply { - whenever(isPackageEnabled("package", mUserHandle)).thenReturn(true) - whenever(isActivityEnabled(mComponentName, mUserHandle)).thenReturn(true) - } - mockContext = - mock().apply { - whenever(packageManager).thenReturn(mock()) - whenever(packageManager.getUserBadgedLabel(any(), any())).thenReturn("") - whenever(applicationContext).thenReturn(ApplicationProvider.getApplicationContext()) - whenever(getSystemService(LauncherApps::class.java)).thenReturn(mockLauncherApps) - } - mockAppState = - mock().apply { - whenever(context).thenReturn(mockContext) - whenever(iconCache).thenReturn(mock()) - whenever(iconCache.getShortcutIcon(any(), any(), any())).then {} - } - mockPmHelper = - mock().apply { - whenever(getAppLaunchIntent(mComponentName.packageName, mUserHandle)) - .thenReturn(intent) - } - mockCursor = - Mockito.mock(LoaderCursor::class.java, RETURNS_DEEP_STUBS).apply { - user = mUserHandle - itemType = ITEM_TYPE_APPLICATION - id = 1 - restoreFlag = 1 - serialNumber = 101 - whenever(parseIntent()).thenReturn(intent) - whenever(markRestored()).doAnswer { restoreFlag = 0 } - whenever(updater().put(Favorites.INTENT, intent.toUri(0)).commit()).thenReturn(1) - whenever(getAppShortcutInfo(any(), any(), any(), any())) - .thenReturn(mockWorkspaceInfo) - whenever(createIconRequestInfo(any(), any())).thenReturn(mockIconRequestInfo) - } - mockUserCache = - mock().apply { - val userIconInfo = - mock().apply { whenever(isPrivate).thenReturn(false) } - whenever(getUserInfo(any())).thenReturn(userIconInfo) - } + mockLauncherApps.apply { + whenever(isPackageEnabled("package", mUserHandle)).thenReturn(true) + whenever(isActivityEnabled(mComponentName, mUserHandle)).thenReturn(true) + } + mockContext.apply { + whenever(packageManager).thenReturn(mock()) + whenever(packageManager.getUserBadgedLabel(any(), any())).thenReturn("") + whenever(applicationContext).thenReturn(ApplicationProvider.getApplicationContext()) + whenever(getSystemService(LauncherApps::class.java)).thenReturn(mockLauncherApps) + } + + whenever(mockIconCache.getShortcutIcon(any(), any(), any())).then {} + whenever(mockPmHelper.getAppLaunchIntent(mComponentName.packageName, mUserHandle)) + .thenReturn(intent) + mockCursor.apply { + user = mUserHandle + itemType = ITEM_TYPE_APPLICATION + id = 1 + restoreFlag = 1 + serialNumber = 101 + whenever(parseIntent()).thenReturn(intent) + whenever(markRestored()).doAnswer { restoreFlag = 0 } + whenever(updater().put(Favorites.INTENT, intent.toUri(0)).commit()).thenReturn(1) + whenever(getAppShortcutInfo(any(), any(), any(), any())).thenReturn(mockWorkspaceInfo) + whenever(createIconRequestInfo(any(), any())).thenReturn(mockIconRequestInfo) + } + + val mockUserInfo = mock().apply { whenever(isPrivate).thenReturn(false) } + whenever(mockUserCache.getUserInfo(any())).thenReturn(mockUserInfo) - mockUserManagerState = mock() - mockWidgetInflater = mock() mKeyToPinnedShortcutsMap = mutableMapOf() mInstallingPkgs = hashMapOf() mAllDeepShortcuts = mutableListOf() @@ -283,7 +268,7 @@ class WorkspaceItemProcessorExtraTest { userManagerState: UserManagerState = mockUserManagerState, launcherApps: LauncherApps = mockLauncherApps, shortcutKeyToPinnedShortcuts: Map = mKeyToPinnedShortcutsMap, - app: LauncherAppState = mockAppState, + context: Context = mockContext, bgDataModel: BgDataModel = mockBgDataModel, widgetProvidersMap: MutableMap = mWidgetProvidersMap, widgetInflater: WidgetInflater = mockWidgetInflater, @@ -297,11 +282,11 @@ class WorkspaceItemProcessorExtraTest { ) = WorkspaceItemProcessor( c = cursor, + context = context, memoryLogger = memoryLogger, userCache = userCache, userManagerState = userManagerState, launcherApps = launcherApps, - app = app, bgDataModel = bgDataModel, widgetProvidersMap = widgetProvidersMap, widgetInflater = widgetInflater, @@ -313,5 +298,8 @@ class WorkspaceItemProcessorExtraTest { shortcutKeyToPinnedShortcuts = shortcutKeyToPinnedShortcuts, installingPkgs = installingPkgs, allDeepShortcuts = allDeepShortcuts, + idp = InvariantDeviceProfile.INSTANCE.get(context), + iconCache = mockIconCache, + isSafeMode = false, ) }