diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 49e0171de1..e058342de7 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -152,6 +152,11 @@ public final class FeatureFlags { false, "Enable loading workspace icons in bulk."); + public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag( + "ENABLE_BULK_ALL_APPS_ICON_LOADING", + false, + "Enable loading all apps icons in bulk."); + // Keep as DeviceFlag for remote disable in emergency. public static final BooleanFlag ENABLE_OVERVIEW_SELECTIONS = new DeviceFlag( "ENABLE_OVERVIEW_SELECTIONS", true, "Show Select Mode button in Overview Actions"); diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java index 92b5885e9e..dbed9a9d58 100644 --- a/src/com/android/launcher3/model/AllAppsList.java +++ b/src/com/android/launcher3/model/AllAppsList.java @@ -130,30 +130,54 @@ public class AllAppsList { * If the app is already in the list, doesn't add it. */ public void add(AppInfo info, LauncherActivityInfo activityInfo) { + add(info, activityInfo, true); + } + + public void add(AppInfo info, LauncherActivityInfo activityInfo, boolean loadIcon) { if (!mAppFilter.shouldShowApp(info.componentName)) { return; } if (findAppInfo(info.componentName, info.user) != null) { return; } - mIconCache.getTitleAndIcon(info, activityInfo, false /* useLowResIcon */); - info.sectionName = mIndex.computeSectionName(info.title); + if (loadIcon) { + mIconCache.getTitleAndIcon(info, activityInfo, false /* useLowResIcon */); + info.sectionName = mIndex.computeSectionName(info.title); + } data.add(info); mDataChanged = true; } - public void addPromiseApp(Context context, PackageInstallInfo installInfo) { - // only if not yet installed - if (!new PackageManagerHelper(context) - .isAppInstalled(installInfo.packageName, installInfo.user)) { - AppInfo info = new AppInfo(installInfo); - mIconCache.getTitleAndIcon(info, info.usingLowResIcon()); - info.sectionName = mIndex.computeSectionName(info.title); + @Nullable + public AppInfo addPromiseApp(Context context, PackageInstallInfo installInfo) { + return addPromiseApp(context, installInfo, true); + } - data.add(info); - mDataChanged = true; + @Nullable + public AppInfo addPromiseApp( + Context context, PackageInstallInfo installInfo, boolean loadIcon) { + // only if not yet installed + if (new PackageManagerHelper(context) + .isAppInstalled(installInfo.packageName, installInfo.user)) { + return null; } + AppInfo promiseAppInfo = new AppInfo(installInfo); + + if (loadIcon) { + mIconCache.getTitleAndIcon(promiseAppInfo, promiseAppInfo.usingLowResIcon()); + promiseAppInfo.sectionName = mIndex.computeSectionName(promiseAppInfo.title); + } + + data.add(promiseAppInfo); + mDataChanged = true; + + return promiseAppInfo; + } + + public void updateSectionName(AppInfo appInfo) { + appInfo.sectionName = mIndex.computeSectionName(appInfo.title); + } /** Updates the given PackageInstallInfo's associated AppInfo's installation info. */ diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 124960679b..cb3af9d477 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -936,6 +936,8 @@ public class LoaderTask implements Runnable { List allActivityList = new ArrayList<>(); // Clear the list of apps mBgAllAppsList.clear(); + + List> iconRequestInfos = new ArrayList<>(); for (UserHandle user : profiles) { // Query for the set of apps final List apps = mLauncherApps.getActivityList(null, user); @@ -948,18 +950,43 @@ public class LoaderTask implements Runnable { // Create the ApplicationInfos for (int i = 0; i < apps.size(); i++) { LauncherActivityInfo app = apps.get(i); - // This builds the icon bitmaps. - mBgAllAppsList.add(new AppInfo(app, user, quietMode), app); + AppInfo appInfo = new AppInfo(app, user, quietMode); + + iconRequestInfos.add(new IconRequestInfo<>( + appInfo, app, /* useLowResIcon= */ false)); + mBgAllAppsList.add( + appInfo, app, !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get()); } allActivityList.addAll(apps); } + if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) { // get all active sessions and add them to the all apps list for (PackageInstaller.SessionInfo info : mSessionHelper.getAllVerifiedSessions()) { - mBgAllAppsList.addPromiseApp(mApp.getContext(), - PackageInstallInfo.fromInstallingState(info)); + AppInfo promiseAppInfo = mBgAllAppsList.addPromiseApp( + mApp.getContext(), + PackageInstallInfo.fromInstallingState(info), + !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get()); + + if (promiseAppInfo != null) { + iconRequestInfos.add(new IconRequestInfo<>( + promiseAppInfo, + /* launcherActivityInfo= */ null, + promiseAppInfo.usingLowResIcon())); + } + } + } + + if (FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get()) { + Trace.beginSection("LoadAllAppsIconsInBulk"); + try { + mIconCache.getTitlesAndIconsInBulk(iconRequestInfos); + iconRequestInfos.forEach(iconRequestInfo -> + mBgAllAppsList.updateSectionName(iconRequestInfo.itemInfo)); + } finally { + Trace.endSection(); } } diff --git a/src/com/android/launcher3/model/data/IconRequestInfo.java b/src/com/android/launcher3/model/data/IconRequestInfo.java index 2f566f6fc0..5dc6a3bb75 100644 --- a/src/com/android/launcher3/model/data/IconRequestInfo.java +++ b/src/com/android/launcher3/model/data/IconRequestInfo.java @@ -47,6 +47,19 @@ public class IconRequestInfo { @Nullable public final byte[] iconBlob; public final boolean useLowResIcon; + public IconRequestInfo( + @NonNull T itemInfo, + @Nullable LauncherActivityInfo launcherActivityInfo, + boolean useLowResIcon) { + this( + itemInfo, + launcherActivityInfo, + /* packageName= */ null, + /* resourceName= */ null, + /* iconBlob= */ null, + useLowResIcon); + } + public IconRequestInfo( @NonNull T itemInfo, @Nullable LauncherActivityInfo launcherActivityInfo,