From f7c32a29fd4468086661b9d64bac6b826438e5ce Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 25 Sep 2024 16:05:04 -0700 Subject: [PATCH] Requesting ApplicationInfo in cached object Bug: 363324203 Test: Presubmit Flag: EXEMPT refactor Change-Id: I92f3d3ed8c267b895dc439ba1f01eb67d7f63965 --- src/com/android/launcher3/Utilities.java | 4 +- .../PinShortcutRequestActivityInfo.java | 3 +- .../launcher3/icons/CacheableShortcutInfo.kt | 131 ++++++++++++++++++ .../android/launcher3/icons/IconCache.java | 33 +++-- .../launcher3/icons/ShortcutCachingLogic.java | 117 ---------------- .../android/launcher3/model/LoaderTask.java | 18 ++- .../launcher3/model/ShortcutsChangedTask.java | 9 +- .../launcher3/model/WorkspaceItemProcessor.kt | 8 +- .../launcher3/pm/PinRequestHelper.java | 6 +- .../pm/ShortcutConfigActivityInfo.java | 23 ++- .../launcher3/popup/PopupPopulator.java | 6 +- .../widget/LauncherAppWidgetProviderInfo.java | 9 ++ .../model/WorkspaceItemProcessorTest.kt | 11 +- .../picker/util/WidgetsTableUtilsTest.java | 2 +- .../model/WorkspaceItemProcessorExtraTest.kt | 5 +- 15 files changed, 227 insertions(+), 158 deletions(-) create mode 100644 src/com/android/launcher3/icons/CacheableShortcutInfo.kt delete mode 100644 src/com/android/launcher3/icons/ShortcutCachingLogic.java diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index fa47449ad2..572274eb9f 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -83,8 +83,8 @@ import androidx.core.graphics.ColorUtils; import com.android.launcher3.dragndrop.FolderAdaptiveIcon; import com.android.launcher3.graphics.TintedDrawableSpan; import com.android.launcher3.icons.BitmapInfo; +import com.android.launcher3.icons.CacheableShortcutInfo; import com.android.launcher3.icons.LauncherIcons; -import com.android.launcher3.icons.ShortcutCachingLogic; import com.android.launcher3.icons.ThemedIconDrawable; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; @@ -635,7 +635,7 @@ public final class Utilities { return null; } else { ShortcutInfo si = siList.get(0); - mainIcon = ShortcutCachingLogic.getIcon(context, si, + mainIcon = CacheableShortcutInfo.getIcon(context, si, appState.getInvariantDeviceProfile().fillResIconDpi); // Only fetch badge if the icon is on workspace if (info.id != ItemInfo.NO_ID && badge == null) { diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java index 0f3cad66a2..cc5e89028d 100644 --- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java +++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java @@ -69,7 +69,8 @@ public class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo { public PinShortcutRequestActivityInfo( ShortcutInfo si, Supplier requestSupplier, Context context) { - super(new ComponentName(si.getPackage(), STUB_COMPONENT_CLASS), si.getUserHandle()); + super(new ComponentName(si.getPackage(), STUB_COMPONENT_CLASS), + si.getUserHandle(), context); mRequestSupplier = requestSupplier; mInfo = si; mContext = context; diff --git a/src/com/android/launcher3/icons/CacheableShortcutInfo.kt b/src/com/android/launcher3/icons/CacheableShortcutInfo.kt new file mode 100644 index 0000000000..c121340e5e --- /dev/null +++ b/src/com/android/launcher3/icons/CacheableShortcutInfo.kt @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2024 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.icons + +import android.content.ComponentName +import android.content.Context +import android.content.pm.LauncherActivityInfo +import android.content.pm.LauncherApps +import android.content.pm.PackageInfo +import android.content.pm.ShortcutInfo +import android.graphics.drawable.Drawable +import android.os.UserHandle +import android.text.TextUtils +import android.util.Log +import com.android.launcher3.BuildConfig +import com.android.launcher3.LauncherAppState +import com.android.launcher3.icons.BaseIconFactory.IconOptions +import com.android.launcher3.icons.cache.BaseIconCache +import com.android.launcher3.icons.cache.CachingLogic +import com.android.launcher3.shortcuts.ShortcutKey +import com.android.launcher3.util.ApplicationInfoWrapper +import com.android.launcher3.util.PackageUserKey +import com.android.launcher3.util.Themes +import kotlin.math.max + +/** Wrapper over ShortcutInfo to provide extra information related to ShortcutInfo */ +class CacheableShortcutInfo(val shortcutInfo: ShortcutInfo, val appInfo: ApplicationInfoWrapper) { + + constructor( + info: ShortcutInfo, + ctx: Context, + ) : this(info, ApplicationInfoWrapper(ctx, info.getPackage(), info.userHandle)) + + companion object { + private const val TAG = "CacheableShortcutInfo" + + /** + * Similar to [LauncherApps.getShortcutIconDrawable] with additional Launcher specific + * checks + */ + @JvmStatic + fun getIcon(context: Context, shortcutInfo: ShortcutInfo, density: Int): Drawable? { + if (!BuildConfig.WIDGETS_ENABLED) { + return null + } + try { + return context + .getSystemService(LauncherApps::class.java) + .getShortcutIconDrawable(shortcutInfo, density) + } catch (e: Exception) { + Log.e(TAG, "Failed to get shortcut icon", e) + return null + } + } + + /** + * Converts the provided list of Shortcuts to CacheableShortcuts by using the application + * info from the provided list of apps + */ + @JvmStatic + fun convertShortcutsToCacheableShortcuts( + shortcuts: List, + activities: List, + ): List { + // Create a map of package to applicationInfo + val appMap = + activities.associateBy( + { PackageUserKey(it.componentName.packageName, it.user) }, + { it.applicationInfo }, + ) + + return shortcuts.map { + CacheableShortcutInfo( + it, + ApplicationInfoWrapper(appMap[PackageUserKey(it.getPackage(), it.userHandle)]), + ) + } + } + } +} + +/** Caching logic for CacheableShortcutInfo. */ +object CacheableShortcutCachingLogic : CachingLogic { + + override fun getComponent(info: CacheableShortcutInfo): ComponentName = + ShortcutKey.fromInfo(info.shortcutInfo).componentName + + override fun getUser(info: CacheableShortcutInfo): UserHandle = info.shortcutInfo.userHandle + + override fun getLabel(info: CacheableShortcutInfo): CharSequence? = info.shortcutInfo.shortLabel + + override fun getDescription(info: CacheableShortcutInfo, fallback: CharSequence): CharSequence = + info.shortcutInfo.longLabel.let { if (TextUtils.isEmpty(it)) fallback else it!! } + + override fun getLastUpdatedTime(info: CacheableShortcutInfo?, packageInfo: PackageInfo) = + info?.let { max(info.shortcutInfo.lastChangedTimestamp, packageInfo.lastUpdateTime) } + ?: packageInfo.lastUpdateTime + + override fun addToMemCache() = false + + override fun getApplicationInfo(info: CacheableShortcutInfo) = info.appInfo.getInfo() + + override fun loadIcon(context: Context, cache: BaseIconCache, info: CacheableShortcutInfo) = + LauncherIcons.obtain(context).use { li -> + CacheableShortcutInfo.getIcon( + context, + info.shortcutInfo, + LauncherAppState.getIDP(context).fillResIconDpi, + ) + ?.let { d -> + li.createBadgedIconBitmap( + d, + IconOptions().setExtractedColor(Themes.getColorAccent(context)), + ) + } ?: BitmapInfo.LOW_RES_INFO + } +} diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java index db05046b1d..5396597ab1 100644 --- a/src/com/android/launcher3/icons/IconCache.java +++ b/src/com/android/launcher3/icons/IconCache.java @@ -65,7 +65,6 @@ import com.android.launcher3.model.data.PackageItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.pm.UserCache; -import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.CancellableTask; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.PackageUserKey; @@ -97,7 +96,6 @@ public class IconCache extends BaseIconCache { private final CachingLogic mComponentWithLabelCachingLogic; private final CachingLogic mLauncherActivityInfoCachingLogic; - private final CachingLogic mShortcutCachingLogic; private final LauncherApps mLauncherApps; private final UserCache mUserManager; @@ -115,7 +113,6 @@ public class IconCache extends BaseIconCache { mComponentWithLabelCachingLogic = new CachedObjectCachingLogic( context, false /* loadIcons */, false /* addToMemCache */); mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.INSTANCE; - mShortcutCachingLogic = new ShortcutCachingLogic(); mLauncherApps = mContext.getSystemService(LauncherApps.class); mUserManager = UserCache.INSTANCE.get(mContext); mInstantAppResolver = InstantAppResolver.newInstance(mContext); @@ -232,7 +229,7 @@ public class IconCache extends BaseIconCache { } /** - * Fill in {@param info} with the icon and label for {@param activityInfo} + * Fill in {@code info} with the icon and label for {@code activityInfo} */ @SuppressWarnings("NewApi") public synchronized void getTitleAndIcon(ItemInfoWithIcon info, @@ -244,28 +241,40 @@ public class IconCache extends BaseIconCache { } /** - * Fill in {@param info} with the icon for {@param si} + * Fill in {@code info} with the icon for {@code si} */ public void getShortcutIcon(ItemInfoWithIcon info, ShortcutInfo si) { + getShortcutIcon(info, new CacheableShortcutInfo(si, mContext)); + } + + /** + * Fill in {@code info} with the icon for {@code si} + */ + public void getShortcutIcon(ItemInfoWithIcon info, CacheableShortcutInfo si) { getShortcutIcon(info, si, mIsUsingFallbackOrNonDefaultIconCheck); } /** - * Fill in {@param info} with the icon and label for {@param si}. If the icon is not + * Fill in {@code info} with the icon and label for {@code si}. If the icon is not * available, and fallback check returns true, it keeps the old icon. */ - public void getShortcutIcon(T info, ShortcutInfo si, + public void getShortcutIcon(T info, CacheableShortcutInfo si, @NonNull Predicate fallbackIconCheck) { - BitmapInfo bitmapInfo = cacheLocked(ShortcutKey.fromInfo(si).componentName, - si.getUserHandle(), () -> si, mShortcutCachingLogic, LookupFlag.DEFAULT).bitmap; + UserHandle user = CacheableShortcutCachingLogic.INSTANCE.getUser(si); + BitmapInfo bitmapInfo = cacheLocked( + CacheableShortcutCachingLogic.INSTANCE.getComponent(si), + user, + () -> si, + CacheableShortcutCachingLogic.INSTANCE, + LookupFlag.DEFAULT).bitmap; if (bitmapInfo.isNullOrLowRes()) { - bitmapInfo = getDefaultIcon(si.getUserHandle()); + bitmapInfo = getDefaultIcon(user); } - if (isDefaultIcon(bitmapInfo, si.getUserHandle()) && fallbackIconCheck.test(info)) { + if (isDefaultIcon(bitmapInfo, user) && fallbackIconCheck.test(info)) { return; } - info.bitmap = bitmapInfo.withBadgeInfo(getShortcutInfoBadge(si)); + info.bitmap = bitmapInfo.withBadgeInfo(getShortcutInfoBadge(si.getShortcutInfo())); } /** diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java deleted file mode 100644 index 7bb39e1230..0000000000 --- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2019 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.icons; - -import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED; - -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.LauncherApps; -import android.content.pm.PackageInfo; -import android.content.pm.ShortcutInfo; -import android.graphics.drawable.Drawable; -import android.os.UserHandle; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.launcher3.LauncherAppState; -import com.android.launcher3.icons.BaseIconFactory.IconOptions; -import com.android.launcher3.icons.cache.BaseIconCache; -import com.android.launcher3.icons.cache.CachingLogic; -import com.android.launcher3.shortcuts.ShortcutKey; -import com.android.launcher3.util.Themes; - -/** - * Caching logic for shortcuts. - */ -public class ShortcutCachingLogic implements CachingLogic { - - private static final String TAG = "ShortcutCachingLogic"; - - @Override - @NonNull - public ComponentName getComponent(@NonNull ShortcutInfo info) { - return ShortcutKey.fromInfo(info).componentName; - } - - @NonNull - @Override - public UserHandle getUser(@NonNull ShortcutInfo info) { - return info.getUserHandle(); - } - - @NonNull - @Override - public CharSequence getLabel(@NonNull ShortcutInfo info) { - return info.getShortLabel(); - } - - @Override - @NonNull - public CharSequence getDescription(@NonNull ShortcutInfo object, - @NonNull CharSequence fallback) { - CharSequence label = object.getLongLabel(); - return TextUtils.isEmpty(label) ? fallback : label; - } - - @NonNull - @Override - public BitmapInfo loadIcon(@NonNull Context context, @NonNull BaseIconCache cache, - @NonNull ShortcutInfo info) { - try (LauncherIcons li = LauncherIcons.obtain(context)) { - Drawable unbadgedDrawable = ShortcutCachingLogic.getIcon( - context, info, LauncherAppState.getIDP(context).fillResIconDpi); - if (unbadgedDrawable == null) return BitmapInfo.LOW_RES_INFO; - return li.createBadgedIconBitmap(unbadgedDrawable, - new IconOptions().setExtractedColor(Themes.getColorAccent(context))); - } - } - - @Override - public long getLastUpdatedTime(@Nullable ShortcutInfo shortcutInfo, - @NonNull PackageInfo info) { - if (shortcutInfo == null) { - return info.lastUpdateTime; - } - return Math.max(shortcutInfo.getLastChangedTimestamp(), info.lastUpdateTime); - } - - @Override - public boolean addToMemCache() { - return false; - } - - /** - * Similar to {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)} with additional - * Launcher specific checks - */ - public static Drawable getIcon(Context context, ShortcutInfo shortcutInfo, int density) { - if (!WIDGETS_ENABLED) { - return null; - } - try { - return context.getSystemService(LauncherApps.class) - .getShortcutIconDrawable(shortcutInfo, density); - } catch (SecurityException | IllegalStateException | NullPointerException e) { - Log.e(TAG, "Failed to get shortcut icon", e); - return null; - } - } -} diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 609846f7fc..dff5463d9a 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -23,6 +23,7 @@ import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle; import static com.android.launcher3.LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE; import static com.android.launcher3.LauncherPrefs.SHOULD_SHOW_SMARTSPACE; import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; +import static com.android.launcher3.icons.CacheableShortcutInfo.convertShortcutsToCacheableShortcuts; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; @@ -69,9 +70,10 @@ import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderGridOrganizer; import com.android.launcher3.folder.FolderNameInfos; import com.android.launcher3.folder.FolderNameProvider; +import com.android.launcher3.icons.CacheableShortcutCachingLogic; +import com.android.launcher3.icons.CacheableShortcutInfo; import com.android.launcher3.icons.ComponentWithLabelAndIcon; import com.android.launcher3.icons.IconCache; -import com.android.launcher3.icons.ShortcutCachingLogic; import com.android.launcher3.icons.cache.CachedObjectCachingLogic; import com.android.launcher3.icons.cache.IconCacheUpdateHandler; import com.android.launcher3.icons.cache.LauncherActivityCachingLogic; @@ -246,7 +248,7 @@ public class LoaderTask implements Runnable { } try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { - List allShortcuts = new ArrayList<>(); + List allShortcuts = new ArrayList<>(); loadWorkspace(allShortcuts, "", memoryLogger, restoreEventLogger); // Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db. @@ -304,7 +306,7 @@ public class LoaderTask implements Runnable { verifyNotStopped(); logASplit("save shortcuts in icon cache"); - updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(), + updateHandler.updateIcons(allShortcuts, CacheableShortcutCachingLogic.INSTANCE, mApp.getModel()::onPackageIconsUpdated); // Take a break @@ -322,8 +324,10 @@ public class LoaderTask implements Runnable { verifyNotStopped(); logASplit("save deep shortcuts in icon cache"); - updateHandler.updateIcons(allDeepShortcuts, - new ShortcutCachingLogic(), (pkgs, user) -> { }); + updateHandler.updateIcons( + convertShortcutsToCacheableShortcuts(allDeepShortcuts, allActivityList), + CacheableShortcutCachingLogic.INSTANCE, + (pkgs, user) -> { }); // Take a break waitForIdle(); @@ -397,7 +401,7 @@ public class LoaderTask implements Runnable { } protected void loadWorkspace( - List allDeepShortcuts, + List allDeepShortcuts, String selection, LoaderMemoryLogger memoryLogger, @Nullable LauncherRestoreEventLogger restoreEventLogger @@ -423,7 +427,7 @@ public class LoaderTask implements Runnable { } private void loadWorkspaceImpl( - List allDeepShortcuts, + List allDeepShortcuts, String selection, @Nullable LoaderMemoryLogger memoryLogger, @Nullable LauncherRestoreEventLogger restoreEventLogger) { diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java index 55c4d30656..b5a7382543 100644 --- a/src/com/android/launcher3/model/ShortcutsChangedTask.java +++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java @@ -24,6 +24,7 @@ import androidx.annotation.NonNull; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel.ModelUpdateTask; import com.android.launcher3.LauncherSettings; +import com.android.launcher3.icons.CacheableShortcutInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; @@ -79,9 +80,9 @@ public class ShortcutsChangedTask implements ModelUpdateTask { } if (!matchingWorkspaceItems.isEmpty()) { + ApplicationInfoWrapper infoWrapper = + new ApplicationInfoWrapper(context, mPackageName, mUser); if (mShortcuts.isEmpty()) { - ApplicationInfoWrapper infoWrapper = - new ApplicationInfoWrapper(context, mPackageName, mUser); // Verify that the app is indeed installed. if (!infoWrapper.isInstalled() && !infoWrapper.isArchived()) { // App is not installed or archived, ignoring package events @@ -103,7 +104,6 @@ public class ShortcutsChangedTask implements ModelUpdateTask { if (!fullDetails.isPinned()) { continue; } - String sid = fullDetails.getId(); nonPinnedIds.remove(sid); matchingWorkspaceItems @@ -111,7 +111,8 @@ public class ShortcutsChangedTask implements ModelUpdateTask { .filter(itemInfo -> sid.equals(itemInfo.getDeepShortcutId())) .forEach(workspaceItemInfo -> { workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context); - app.getIconCache().getShortcutIcon(workspaceItemInfo, fullDetails); + app.getIconCache().getShortcutIcon(workspaceItemInfo, + new CacheableShortcutInfo(fullDetails, infoWrapper)); updatedWorkspaceItemInfos.add(workspaceItemInfo); }); } diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt index 18c7f955eb..c02336ec4e 100644 --- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt +++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt @@ -32,6 +32,7 @@ import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings.Favorites import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError import com.android.launcher3.config.FeatureFlags +import com.android.launcher3.icons.CacheableShortcutInfo import com.android.launcher3.logging.FileLog import com.android.launcher3.model.data.AppInfo import com.android.launcher3.model.data.AppPairInfo @@ -76,7 +77,7 @@ class WorkspaceItemProcessor( private val pmHelper: PackageManagerHelper, private val iconRequestInfos: MutableList>, private val unlockedUsers: LongSparseArray, - private val allDeepShortcuts: MutableList, + private val allDeepShortcuts: MutableList, ) { private val isSafeMode = app.isSafeModeEnabled @@ -278,13 +279,14 @@ class WorkspaceItemProcessor( info = WorkspaceItemInfo(pinnedShortcut, app.context) // If the pinned deep shortcut is no longer published, // use the last saved icon instead of the default. - iconCache.getShortcutIcon(info, pinnedShortcut, c::loadIcon) + val csi = CacheableShortcutInfo(pinnedShortcut, appInfoWrapper) + iconCache.getShortcutIcon(info, csi, c::loadIcon) if (appInfoWrapper.isSuspended()) { info.runtimeStatusFlags = info.runtimeStatusFlags or ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED } intent = info.getIntent() - allDeepShortcuts.add(pinnedShortcut) + allDeepShortcuts.add(csi) } else { // Create a shortcut info in disabled mode for now. info = c.loadSimpleWorkspaceItem() diff --git a/src/com/android/launcher3/pm/PinRequestHelper.java b/src/com/android/launcher3/pm/PinRequestHelper.java index 47afeef703..2ed6591a35 100644 --- a/src/com/android/launcher3/pm/PinRequestHelper.java +++ b/src/com/android/launcher3/pm/PinRequestHelper.java @@ -32,7 +32,8 @@ import android.os.SystemClock; import androidx.annotation.Nullable; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.icons.ShortcutCachingLogic; +import com.android.launcher3.icons.CacheableShortcutCachingLogic; +import com.android.launcher3.icons.CacheableShortcutInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; public class PinRequestHelper { @@ -78,7 +79,8 @@ public class PinRequestHelper { // Apply the unbadged icon synchronously using the caching logic directly and // fetch the actual icon asynchronously. LauncherAppState app = LauncherAppState.getInstance(context); - info.bitmap = new ShortcutCachingLogic().loadIcon(context, app.getIconCache(), si); + info.bitmap = CacheableShortcutCachingLogic.INSTANCE.loadIcon( + context, app.getIconCache(), new CacheableShortcutInfo(si, context)); app.getModel().updateAndBindWorkspaceItem(info, si); return info; } else { diff --git a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java index 02938d0609..3064abfc9f 100644 --- a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java +++ b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java @@ -26,6 +26,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentSender; +import android.content.pm.ApplicationInfo; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; @@ -43,6 +44,7 @@ import com.android.launcher3.R; import com.android.launcher3.icons.ComponentWithLabelAndIcon; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.data.WorkspaceItemInfo; +import com.android.launcher3.util.ApplicationInfoWrapper; import com.android.launcher3.util.PackageUserKey; import java.util.ArrayList; @@ -58,10 +60,20 @@ public abstract class ShortcutConfigActivityInfo implements ComponentWithLabelAn private final ComponentName mCn; private final UserHandle mUser; + private final ApplicationInfoWrapper mInfoWrapper; - protected ShortcutConfigActivityInfo(ComponentName cn, UserHandle user) { + protected ShortcutConfigActivityInfo( + ComponentName cn, UserHandle user, ApplicationInfoWrapper infoWrapper) { mCn = cn; mUser = user; + mInfoWrapper = infoWrapper; + } + + protected ShortcutConfigActivityInfo( + ComponentName cn, UserHandle user, Context context) { + mCn = cn; + mUser = user; + mInfoWrapper = new ApplicationInfoWrapper(context, cn.getPackageName(), user); } @Override @@ -89,6 +101,12 @@ public abstract class ShortcutConfigActivityInfo implements ComponentWithLabelAn return null; } + @Nullable + @Override + public ApplicationInfo getApplicationInfo() { + return mInfoWrapper.getInfo(); + } + public boolean startConfigActivity(Activity activity, int requestCode) { Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT) .setComponent(getComponent()); @@ -120,7 +138,8 @@ public abstract class ShortcutConfigActivityInfo implements ComponentWithLabelAn private final LauncherActivityInfo mInfo; public ShortcutConfigActivityInfoVO(LauncherActivityInfo info) { - super(info.getComponentName(), info.getUser()); + super(info.getComponentName(), info.getUser(), + new ApplicationInfoWrapper(info.getApplicationInfo())); mInfo = info; } diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java index aa24f60b72..755c3ebcec 100644 --- a/src/com/android/launcher3/popup/PopupPopulator.java +++ b/src/com/android/launcher3/popup/PopupPopulator.java @@ -27,11 +27,13 @@ import android.os.UserHandle; import androidx.annotation.VisibleForTesting; import com.android.launcher3.LauncherAppState; +import com.android.launcher3.icons.CacheableShortcutInfo; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.launcher3.shortcuts.ShortcutRequest; +import com.android.launcher3.util.ApplicationInfoWrapper; import com.android.launcher3.views.ActivityContext; import java.util.ArrayList; @@ -113,6 +115,8 @@ public class PopupPopulator { final ComponentName activity = originalInfo.getTargetComponent(); final UserHandle user = originalInfo.user; return () -> { + ApplicationInfoWrapper infoWrapper = + new ApplicationInfoWrapper(context, activity.getPackageName(), user); List shortcuts = new ShortcutRequest(context, user) .withContainer(activity) .query(ShortcutRequest.PUBLISHED); @@ -121,7 +125,7 @@ public class PopupPopulator { for (int i = 0; i < shortcuts.size() && i < shortcutViews.size(); i++) { final ShortcutInfo shortcut = shortcuts.get(i); final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, context); - cache.getShortcutIcon(si, shortcut); + cache.getShortcutIcon(si, new CacheableShortcutInfo(shortcut, infoWrapper)); si.rank = i; si.container = CONTAINER_SHORTCUTS; diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java index 3559554607..1db3b5a4af 100644 --- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java +++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java @@ -3,6 +3,7 @@ package com.android.launcher3.widget; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.graphics.Point; import android.graphics.Rect; @@ -10,6 +11,8 @@ import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.UserHandle; +import androidx.annotation.Nullable; + import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; @@ -225,4 +228,10 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo public Drawable getFullResIcon(IconCache cache) { return cache.getFullResIcon(getActivityInfo()); } + + @Nullable + @Override + public ApplicationInfo getApplicationInfo() { + return getActivityInfo().applicationInfo; + } } \ No newline at end of file diff --git a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt index 7529ba9b12..c7abce6e5e 100644 --- a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt @@ -40,6 +40,7 @@ import com.android.launcher3.backuprestore.LauncherRestoreEventLogger import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.MISSING_INFO import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.MISSING_WIDGET_PROVIDER import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.PROFILE_DELETED +import com.android.launcher3.icons.CacheableShortcutInfo import com.android.launcher3.model.data.FolderInfo import com.android.launcher3.model.data.IconRequestInfo import com.android.launcher3.model.data.ItemInfo @@ -97,7 +98,7 @@ class WorkspaceItemProcessorTest { private var mUnlockedUsersArray: LongSparseArray = LongSparseArray() private var mKeyToPinnedShortcutsMap: MutableMap = mutableMapOf() private var mInstallingPkgs: HashMap = hashMapOf() - private var mAllDeepShortcuts: MutableList = mutableListOf() + private var mAllDeepShortcuts: MutableList = mutableListOf() private var mWidgetProvidersMap: MutableMap = mutableMapOf() private var mPendingPackages: MutableSet = mutableSetOf() @@ -194,7 +195,7 @@ class WorkspaceItemProcessorTest { pendingPackages: MutableSet = mPendingPackages, unlockedUsers: LongSparseArray = mUnlockedUsersArray, installingPkgs: HashMap = mInstallingPkgs, - allDeepShortcuts: MutableList = mAllDeepShortcuts, + allDeepShortcuts: MutableList = mAllDeepShortcuts, ) = WorkspaceItemProcessor( c = cursor, @@ -387,7 +388,8 @@ class WorkspaceItemProcessorTest { .that(mockCursor.restoreFlag) .isEqualTo(0) assertThat(mIconRequestInfos).isEmpty() - assertThat(mAllDeepShortcuts).containsExactly(expectedShortcutInfo) + assertThat(mAllDeepShortcuts.size).isEqualTo(1) + assertThat(mAllDeepShortcuts[0].shortcutInfo).isEqualTo(expectedShortcutInfo) verify(mockCursor).markRestored() verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull()) } @@ -452,7 +454,8 @@ class WorkspaceItemProcessorTest { .that(mockCursor.restoreFlag) .isEqualTo(0) assertThat(mIconRequestInfos).isEmpty() - assertThat(mAllDeepShortcuts).containsExactly(expectedShortcutInfo) + assertThat(mAllDeepShortcuts.size).isEqualTo(1) + assertThat(mAllDeepShortcuts[0].shortcutInfo).isEqualTo(expectedShortcutInfo) verify(mockCursor).markRestored() verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull()) } diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java index b2cb26613d..7adb2b17f4 100644 --- a/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java +++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java @@ -296,7 +296,7 @@ public final class WidgetsTableUtilsTest { private final class TestShortcutConfigActivityInfo extends ShortcutConfigActivityInfo { TestShortcutConfigActivityInfo(ComponentName componentName, UserHandle user) { - super(componentName, user); + super(componentName, user, mContext); } @Override diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt index f1b62719bf..d553f470d0 100644 --- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt +++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt @@ -35,6 +35,7 @@ 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.model.data.IconRequestInfo import com.android.launcher3.model.data.LauncherAppWidgetInfo import com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_RESTORE_STARTED @@ -84,7 +85,7 @@ class WorkspaceItemProcessorExtraTest { private var mUnlockedUsersArray: LongSparseArray = LongSparseArray() private var mKeyToPinnedShortcutsMap: MutableMap = mutableMapOf() private var mInstallingPkgs: HashMap = hashMapOf() - private var mAllDeepShortcuts: MutableList = mutableListOf() + private var mAllDeepShortcuts: MutableList = mutableListOf() private var mWidgetProvidersMap: MutableMap = mutableMapOf() private var mPendingPackages: MutableSet = mutableSetOf() @@ -290,7 +291,7 @@ class WorkspaceItemProcessorExtraTest { pendingPackages: MutableSet = mPendingPackages, unlockedUsers: LongSparseArray = mUnlockedUsersArray, installingPkgs: HashMap = mInstallingPkgs, - allDeepShortcuts: MutableList = mAllDeepShortcuts, + allDeepShortcuts: MutableList = mAllDeepShortcuts, ) = WorkspaceItemProcessor( c = cursor,