From 41998110bd4d367cd99c0ff393b9c90555c99fd1 Mon Sep 17 00:00:00 2001 From: Anushree Ganjam Date: Fri, 18 Apr 2025 23:07:01 +0000 Subject: [PATCH] Move FolderNameProvider to dagger. Helps us to delete ResourceBasedOverride class. Delete "folder_name_provider_class" resource from config. Introduce FolderNameSuggestionLoader for easy dagger injection for folderNameProvider. Bug: 361850561 Test: Presubmit Flag: EXEMPT dagger Change-Id: I58a68cb4ce11331458a1cccef2e692f74c14ea53 --- res/values/config.xml | 1 - src/com/android/launcher3/DropTarget.java | 10 ++-- .../dagger/LauncherBaseAppComponent.java | 3 +- src/com/android/launcher3/folder/Folder.java | 11 ++-- .../android/launcher3/folder/FolderIcon.java | 15 ++--- .../launcher3/folder/FolderNameProvider.java | 50 +++------------- .../folder/FolderNameSuggestionLoader.kt | 60 +++++++++++++++++++ .../android/launcher3/model/LoaderTask.java | 9 ++- .../WidgetRecommendationCategoryProvider.java | 7 +-- 9 files changed, 94 insertions(+), 72 deletions(-) create mode 100644 src/com/android/launcher3/folder/FolderNameSuggestionLoader.kt diff --git a/res/values/config.xml b/res/values/config.xml index f8c95ab974..a012d353f5 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -61,7 +61,6 @@ 200 - diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java index 7f0c7b50c0..3b22d5caaf 100644 --- a/src/com/android/launcher3/DropTarget.java +++ b/src/com/android/launcher3/DropTarget.java @@ -21,14 +21,14 @@ import android.graphics.Rect; import android.view.View; import com.android.launcher3.accessibility.DragViewStateAnnouncer; +import com.android.launcher3.dagger.LauncherComponentProvider; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.dragndrop.DraggableView; -import com.android.launcher3.folder.FolderNameProvider; +import com.android.launcher3.folder.FolderNameSuggestionLoader; import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.InstanceIdSequence; import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.util.Executors; /** * Interface defining an object that can receive a drag. @@ -72,7 +72,7 @@ public interface DropTarget { public DragViewStateAnnouncer stateAnnouncer; - public FolderNameProvider folderNameProvider; + public FolderNameSuggestionLoader folderNameSuggestionLoader; /** The source view (ie. icon, widget etc.) that is being dragged and which the * DragView represents. May be an actual View class or a virtual stand-in */ @@ -82,8 +82,8 @@ public interface DropTarget { public final InstanceId logInstanceId = new InstanceIdSequence().newInstanceId(); public DragObject(Context context) { - Executors.MODEL_EXECUTOR.post(() -> - folderNameProvider = FolderNameProvider.newInstance(context)); + folderNameSuggestionLoader = LauncherComponentProvider.get(context) + .getFolderNameSuggestionLoader(); } /** diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java index a9bad2049d..45d339b474 100644 --- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java +++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java @@ -24,6 +24,7 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.RemoveAnimationSettingsTracker; +import com.android.launcher3.folder.FolderNameSuggestionLoader; import com.android.launcher3.graphics.GridCustomizationsProxy; import com.android.launcher3.graphics.ThemeManager; import com.android.launcher3.icons.LauncherIcons.IconPool; @@ -89,7 +90,7 @@ public interface LauncherBaseAppComponent { RemoveAnimationSettingsTracker getRemoveAnimationSettingsTracker(); LauncherAppState getLauncherAppState(); GridCustomizationsProxy getGridCustomizationsProxy(); - + FolderNameSuggestionLoader getFolderNameSuggestionLoader(); LoaderCursorFactory getLoaderCursorFactory(); WidgetHolderFactory getWidgetHolderFactory(); RefreshRateTracker getFrameRateProvider(); diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 874c673c6b..90367009e0 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -92,6 +92,7 @@ import com.android.launcher3.accessibility.FolderAccessibilityHelper; import com.android.launcher3.anim.KeyboardInsetAnimationCallback; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dagger.LauncherComponentProvider; import com.android.launcher3.dragndrop.DragController.DragListener; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.graphics.ShapeDelegate; @@ -106,7 +107,6 @@ import com.android.launcher3.model.data.WorkspaceItemFactory; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pageindicators.PageIndicatorDots; import com.android.launcher3.pageindicators.PaginationArrow; -import com.android.launcher3.util.Executors; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.Thunk; import com.android.launcher3.views.ActivityContext; @@ -1220,12 +1220,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mActivityContext.getModelWriter().moveItemsInDatabase(items, mInfo.id, 0); } if (!isBind && total > 1 /* no need to update if there's one icon */) { - Executors.MODEL_EXECUTOR.post(() -> { - FolderNameInfos nameInfos = new FolderNameInfos(); - FolderNameProvider fnp = FolderNameProvider.newInstance(getContext()); - fnp.getSuggestedFolderName(getContext(), mInfo.getAppContents(), nameInfos); - mInfo.suggestedFolderNames = nameInfos; - }); + LauncherComponentProvider.get(getContext()).getFolderNameSuggestionLoader() + .getSuggestedFolderName(mInfo.getAppContents(), + folderNameInfos -> mInfo.suggestedFolderNames = folderNameInfos); } } diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 23045507d1..17bff899af 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -79,7 +79,6 @@ import com.android.launcher3.model.data.FolderInfo.LabelState; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemFactory; import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.util.Executors; import com.android.launcher3.util.MultiTranslateDelegate; import com.android.launcher3.util.Thunk; import com.android.launcher3.views.ActivityContext; @@ -403,16 +402,12 @@ public class FolderIcon extends FrameLayout implements FloatingIconViewCompanion mFolder.hideItem(item); if (!itemAdded) mPreviewItemManager.hidePreviewItem(index, true); + d.folderNameSuggestionLoader.getSuggestedFolderName(mInfo.getAppContents(), + folderNameInfos -> postDelayed(() -> { + setLabelSuggestion(folderNameInfos, d.logInstanceId); + invalidate(); + }, DROP_IN_ANIMATION_DURATION)); - FolderNameInfos nameInfos = new FolderNameInfos(); - Executors.MODEL_EXECUTOR.post(() -> { - d.folderNameProvider.getSuggestedFolderName( - getContext(), mInfo.getAppContents(), nameInfos); - postDelayed(() -> { - setLabelSuggestion(nameInfos, d.logInstanceId); - invalidate(); - }, DROP_IN_ANIMATION_DURATION); - }); } else { getFolder().addFolderContent(item); } diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java index 8a1f96d2dd..3d21c1f519 100644 --- a/src/com/android/launcher3/folder/FolderNameProvider.java +++ b/src/com/android/launcher3/folder/FolderNameProvider.java @@ -26,16 +26,11 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; -import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; -import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherModel.ModelUpdateTask; import com.android.launcher3.R; import com.android.launcher3.Utilities; -import com.android.launcher3.model.AllAppsList; import com.android.launcher3.model.BgDataModel; -import com.android.launcher3.model.ModelTaskController; import com.android.launcher3.model.StringCache; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.CollectionInfo; @@ -43,20 +38,20 @@ import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.util.IntSparseArrayMap; import com.android.launcher3.util.Preconditions; -import com.android.launcher3.util.ResourceBasedOverride; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import javax.inject.Inject; + /** * Locates provider for the folder name. */ -public class FolderNameProvider implements ResourceBasedOverride { +public class FolderNameProvider { private static final String TAG = "FolderNameProvider"; private static final boolean DEBUG = false; @@ -70,34 +65,17 @@ public class FolderNameProvider implements ResourceBasedOverride { protected List mAppInfos; /** - * Retrieve instance of this object that can be overridden in runtime based on the build - * variant of the application. + * FolderNameProvider should be constructed on a background thread always. + * If you want to inject FolderNameProvider, use {@link FolderNameSuggestionLoader} or use + * {@link javax.inject.Provider} to create the FolderNameProvider in background thread */ - public static FolderNameProvider newInstance(Context context) { - FolderNameProvider fnp = Overrides.getObject(FolderNameProvider.class, - context.getApplicationContext(), R.string.folder_name_provider_class); + @Inject + public FolderNameProvider() { Preconditions.assertWorkerThread(); - fnp.load(context); - - return fnp; } - public static FolderNameProvider newInstance(Context context, List appInfos, - IntSparseArrayMap folderInfos) { + public void load(List appInfos, IntSparseArrayMap folderInfos) { Preconditions.assertWorkerThread(); - FolderNameProvider fnp = Overrides.getObject(FolderNameProvider.class, - context.getApplicationContext(), R.string.folder_name_provider_class); - fnp.load(appInfos, folderInfos); - - return fnp; - } - - private void load(Context context) { - LauncherAppState.getInstance(context).getModel().enqueueModelUpdateTask( - new FolderNameWorker()); - } - - private void load(List appInfos, IntSparseArrayMap folderInfos) { mAppInfos = appInfos; mCollectionInfos = folderInfos; } @@ -195,16 +173,6 @@ public class FolderNameProvider implements ResourceBasedOverride { nameInfos.setLabel(labels.length - 1, label, 1.0f); } - private class FolderNameWorker implements ModelUpdateTask { - - @Override - public void execute(@NonNull ModelTaskController taskController, - @NonNull BgDataModel dataModel, @NonNull AllAppsList apps) { - mCollectionInfos = getCollectionForSuggestions(dataModel); - mAppInfos = Arrays.asList(apps.copyData()); - } - } - public static IntSparseArrayMap getCollectionForSuggestions( BgDataModel dataModel) { IntSparseArrayMap result = new IntSparseArrayMap<>(); diff --git a/src/com/android/launcher3/folder/FolderNameSuggestionLoader.kt b/src/com/android/launcher3/folder/FolderNameSuggestionLoader.kt new file mode 100644 index 0000000000..9e6a71c948 --- /dev/null +++ b/src/com/android/launcher3/folder/FolderNameSuggestionLoader.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.folder + +import android.content.Context +import androidx.core.util.Consumer +import com.android.launcher3.LauncherModel +import com.android.launcher3.dagger.ApplicationContext +import com.android.launcher3.model.data.WorkspaceItemInfo +import com.android.launcher3.util.Executors.MODEL_EXECUTOR +import javax.inject.Inject +import javax.inject.Provider + +class FolderNameSuggestionLoader +@Inject +constructor( + @ApplicationContext private val context: Context, + private val folderNameProviderFactory: Provider, + private val model: LauncherModel, +) { + + var folderNameProvider: FolderNameProvider? = null + + init { + MODEL_EXECUTOR.execute { + folderNameProvider = folderNameProviderFactory.get() + model.enqueueModelUpdateTask { _, dataModel, appList -> + folderNameProvider?.load( + appList.copyData().asList(), + FolderNameProvider.getCollectionForSuggestions(dataModel), + ) + } + } + } + + fun getSuggestedFolderName( + workspaceItemInfos: ArrayList, + callback: Consumer, + ) { + MODEL_EXECUTOR.execute { + val nameInfos = FolderNameInfos() + folderNameProvider?.getSuggestedFolderName(context, workspaceItemInfos, nameInfos) + callback.accept(nameInfos) + } + } +} diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 2c6583558a..27d242cc57 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -120,6 +120,7 @@ import java.util.Set; import java.util.concurrent.CancellationException; import javax.inject.Named; +import javax.inject.Provider; /** * Runnable for the thread that loads the contents of the launcher: @@ -169,6 +170,7 @@ public class LoaderTask implements Runnable { private final Set mPendingPackages = new HashSet<>(); private boolean mItemsDeleted = false; private String mDbName; + private final Provider mFolderNameProviderFactory; @AssistedInject LoaderTask( @@ -182,6 +184,7 @@ public class LoaderTask implements Runnable { AllAppsList bgAllAppsList, BgDataModel bgModel, LoaderCursorFactory loaderCursorFactory, + Provider folderNameProviderFactory, @Named("SAFE_MODE") boolean isSafeModeEnabled, @Assisted @NonNull BaseLauncherBinder launcherBinder, @Assisted UserManagerState userManagerState) { @@ -202,6 +205,7 @@ public class LoaderTask implements Runnable { mIconCache = iconCache; mUserManagerState = userManagerState; mInstallingPkgsCached = null; + mFolderNameProviderFactory = folderNameProviderFactory; } protected synchronized void waitForIdle() { @@ -879,8 +883,9 @@ public class LoaderTask implements Runnable { } private void loadFolderNames() { - FolderNameProvider provider = FolderNameProvider.newInstance(mContext, - mBgAllAppsList.data, FolderNameProvider.getCollectionForSuggestions(mBgDataModel)); + FolderNameProvider provider = mFolderNameProviderFactory.get(); + provider.load(mBgAllAppsList.data, + FolderNameProvider.getCollectionForSuggestions(mBgDataModel)); synchronized (mBgDataModel) { mBgDataModel.itemsIdMap.stream() diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java index 8f34fe3572..49a1696f8c 100644 --- a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java +++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java @@ -26,13 +26,10 @@ import com.android.launcher3.R; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.util.ApplicationInfoWrapper; import com.android.launcher3.util.Preconditions; -import com.android.launcher3.util.ResourceBasedOverride; /** - * A {@link ResourceBasedOverride} that categorizes widget recommendations. - * - *

Override the {@code widget_recommendation_category_provider_class} resource to provide your - * own implementation. Method {@code getWidgetRecommendationCategory} is called per widget to get + * To categorize widget recommendations. + * Method {@code getWidgetRecommendationCategory} is called per widget to get * the category.

*/ public class WidgetRecommendationCategoryProvider {