diff options
6 files changed, 119 insertions, 18 deletions
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java index 09f59b84c..16bc7ae83 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java +++ b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java @@ -17,6 +17,7 @@ package com.android.launcher3.icons.cache; import android.content.ComponentName; import android.content.Context; +import android.content.pm.PackageInfo; import android.os.LocaleList; import android.os.UserHandle; @@ -41,4 +42,11 @@ public interface CachingLogic<T> { default String getKeywords(T object, LocaleList localeList) { return null; } + + /** + * Returns the timestamp the entry was last updated in cache. + */ + default long getLastUpdatedTime(T object, PackageInfo info) { + return info.lastUpdateTime; + } } diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java index 3c71bd027..bcdbce5e2 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java +++ b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java @@ -171,8 +171,9 @@ public class IconCacheUpdateHandler { long updateTime = c.getLong(indexLastUpdate); int version = c.getInt(indexVersion); T app = componentMap.remove(component); - if (version == info.versionCode && updateTime == info.lastUpdateTime && - TextUtils.equals(c.getString(systemStateIndex), + if (version == info.versionCode + && updateTime == cachingLogic.getLastUpdatedTime(app, info) + && TextUtils.equals(c.getString(systemStateIndex), mIconCache.getIconSystemState(info.packageName))) { if (mFilterMode == MODE_CLEAR_VALID_ITEMS) { @@ -231,7 +232,6 @@ public class IconCacheUpdateHandler { } } - /** * A runnable that updates invalid icons and adds missing icons in the DB for the provided * LauncherActivityInfo list. Items are updated/added one at a time, so that the diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java index a8ff23275..50b5222d3 100644 --- a/src/com/android/launcher3/icons/IconCache.java +++ b/src/com/android/launcher3/icons/IconCache.java @@ -26,6 +26,7 @@ import android.content.pm.LauncherActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ShortcutInfo; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Process; @@ -49,6 +50,7 @@ import com.android.launcher3.icons.cache.BaseIconCache; import com.android.launcher3.icons.cache.CachingLogic; import com.android.launcher3.icons.cache.HandlerRunnable; import com.android.launcher3.model.PackageItemInfo; +import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.Preconditions; @@ -63,6 +65,7 @@ public class IconCache extends BaseIconCache { private final CachingLogic<ComponentWithLabel> mComponentWithLabelCachingLogic; private final CachingLogic<LauncherActivityInfo> mLauncherActivityInfoCachingLogic; + private final CachingLogic<ShortcutInfo> mShortcutCachingLogic; private final LauncherAppsCompat mLauncherApps; private final UserManagerCompat mUserManager; @@ -76,6 +79,7 @@ public class IconCache extends BaseIconCache { inv.fillResIconDpi, inv.iconBitmapSize, true /* inMemoryCache */); mComponentWithLabelCachingLogic = new ComponentCachingLogic(context); mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.newInstance(context); + mShortcutCachingLogic = new ShortcutCachingLogic(); mLauncherApps = LauncherAppsCompat.getInstance(mContext); mUserManager = UserManagerCompat.getInstance(mContext); mInstantAppResolver = InstantAppResolver.newInstance(mContext); @@ -174,6 +178,14 @@ public class IconCache extends BaseIconCache { } /** + * Fill in info with the icon and label for deep shortcut. + */ + public synchronized CacheEntry getDeepShortcutTitleAndIcon(ShortcutInfo info) { + return cacheLocked(ShortcutKey.fromInfo(info).componentName, info.getUserHandle(), + () -> info, mShortcutCachingLogic, false, false); + } + + /** * Fill in {@param info} with the icon and label. If the * corresponding activity is not found, it reverts to the package icon. */ diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java index 763240885..c6949afc3 100644 --- a/src/com/android/launcher3/icons/LauncherIcons.java +++ b/src/com/android/launcher3/icons/LauncherIcons.java @@ -21,9 +21,10 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ShortcutInfo; import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; import android.os.Process; +import androidx.annotation.Nullable; + import com.android.launcher3.AppInfo; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.InvariantDeviceProfile; @@ -31,14 +32,12 @@ import com.android.launcher3.ItemInfoWithIcon; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.graphics.IconShape; +import com.android.launcher3.icons.cache.BaseIconCache; import com.android.launcher3.model.PackageItemInfo; -import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.util.Themes; import java.util.function.Supplier; -import androidx.annotation.Nullable; - /** * Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class * that are threadsafe. @@ -126,13 +125,12 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable { public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged, @Nullable Supplier<ItemInfoWithIcon> fallbackIconProvider) { - Drawable unbadgedDrawable = DeepShortcutManager.getInstance(mContext) - .getShortcutIconDrawable(shortcutInfo, mFillResIconDpi); IconCache cache = LauncherAppState.getInstance(mContext).getIconCache(); + BaseIconCache.CacheEntry entry = cache.getDeepShortcutTitleAndIcon(shortcutInfo); final Bitmap unbadgedBitmap; - if (unbadgedDrawable != null) { - unbadgedBitmap = createScaledBitmapWithoutShadow(unbadgedDrawable, 0); + if (entry.icon != null) { + unbadgedBitmap = entry.icon; } else { if (fallbackIconProvider != null) { // Fallback icons are already badged and with appropriate shadow diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java new file mode 100644 index 000000000..ee79b249c --- /dev/null +++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java @@ -0,0 +1,67 @@ +/* + * 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 android.content.ComponentName; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.ShortcutInfo; +import android.graphics.drawable.Drawable; +import android.os.UserHandle; + +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.icons.cache.CachingLogic; +import com.android.launcher3.shortcuts.DeepShortcutManager; +import com.android.launcher3.shortcuts.ShortcutKey; + +/** + * Caching logic for shortcuts. + */ +public class ShortcutCachingLogic implements CachingLogic<ShortcutInfo> { + + @Override + public ComponentName getComponent(ShortcutInfo info) { + return ShortcutKey.fromInfo(info).componentName; + } + + @Override + public UserHandle getUser(ShortcutInfo info) { + return info.getUserHandle(); + } + + @Override + public CharSequence getLabel(ShortcutInfo info) { + return info.getShortLabel(); + } + + @Override + public void loadIcon(Context context, ShortcutInfo info, BitmapInfo target) { + LauncherIcons li = LauncherIcons.obtain(context); + Drawable unbadgedDrawable = DeepShortcutManager.getInstance(context) + .getShortcutIconDrawable(info, LauncherAppState.getIDP(context).fillResIconDpi); + if (unbadgedDrawable != null) { + target.icon = li.createScaledBitmapWithoutShadow(unbadgedDrawable, 0); + } + li.recycle(); + } + + @Override + public long getLastUpdatedTime(ShortcutInfo shortcutInfo, PackageInfo info) { + if (shortcutInfo == null) return info.lastUpdateTime; + return Math.max(shortcutInfo.getLastChangedTimestamp(), info.lastUpdateTime); + } +} diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 60e917d1d..c3f5bc7af 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -63,6 +63,7 @@ import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic; import com.android.launcher3.icons.IconCache; import com.android.launcher3.icons.LauncherActivityCachingLogic; import com.android.launcher3.icons.LauncherIcons; +import com.android.launcher3.icons.ShortcutCachingLogic; import com.android.launcher3.icons.cache.IconCacheUpdateHandler; import com.android.launcher3.logging.FileLog; import com.android.launcher3.provider.ImportDataTask; @@ -170,7 +171,8 @@ public class LoaderTask implements Runnable { TraceHelper.beginSection(TAG); try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { TraceHelper.partitionSection(TAG, "step 1.1: loading workspace"); - loadWorkspace(); + List<ShortcutInfo> allShortcuts = new ArrayList<>(); + loadWorkspace(allShortcuts); verifyNotStopped(); TraceHelper.partitionSection(TAG, "step 1.2: bind workspace workspace"); @@ -189,18 +191,23 @@ public class LoaderTask implements Runnable { TraceHelper.partitionSection(TAG, "step 2.1: loading all apps"); List<LauncherActivityInfo> allActivityList = loadAllApps(); - TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps"); + TraceHelper.partitionSection(TAG, "step 2.2: binding all apps"); verifyNotStopped(); mResults.bindAllApps(); verifyNotStopped(); - TraceHelper.partitionSection(TAG, "step 2.3: Update icon cache"); + TraceHelper.partitionSection(TAG, "step 2.3: save app icons in icon cache"); IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler(); setIgnorePackages(updateHandler); updateHandler.updateIcons(allActivityList, LauncherActivityCachingLogic.newInstance(mApp.getContext()), mApp.getModel()::onPackageIconsUpdated); + verifyNotStopped(); + TraceHelper.partitionSection(TAG, "step 2.4: save shortcuts in icon cache"); + updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(), + mApp.getModel()::onPackageIconsUpdated); + // Take a break TraceHelper.partitionSection(TAG, "step 2 completed, wait for idle"); waitForIdle(); @@ -208,12 +215,17 @@ public class LoaderTask implements Runnable { // third step TraceHelper.partitionSection(TAG, "step 3.1: loading deep shortcuts"); - loadDeepShortcuts(); + List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts(); verifyNotStopped(); TraceHelper.partitionSection(TAG, "step 3.2: bind deep shortcuts"); mResults.bindDeepShortcuts(); + verifyNotStopped(); + TraceHelper.partitionSection(TAG, "step 3.3: save deep shortcuts in icon cache"); + updateHandler.updateIcons(allDeepShortcuts, + new ShortcutCachingLogic(), (pkgs, user) -> { }); + // Take a break TraceHelper.partitionSection(TAG, "step 3 completed, wait for idle"); waitForIdle(); @@ -228,7 +240,7 @@ public class LoaderTask implements Runnable { mResults.bindWidgets(); verifyNotStopped(); - TraceHelper.partitionSection(TAG, "step 4.3: Update icon cache"); + TraceHelper.partitionSection(TAG, "step 4.3: save widgets in icon cache"); updateHandler.updateIcons(allWidgetsList, new ComponentCachingLogic(mApp.getContext()), mApp.getModel()::onWidgetLabelsUpdated); @@ -249,7 +261,7 @@ public class LoaderTask implements Runnable { this.notify(); } - private void loadWorkspace() { + private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts) { final Context context = mApp.getContext(); final ContentResolver contentResolver = context.getContentResolver(); final PackageManagerHelper pmHelper = new PackageManagerHelper(context); @@ -498,6 +510,7 @@ public class LoaderTask implements Runnable { info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED; } intent = info.intent; + allDeepShortcuts.add(pinnedShortcut); } else { // Create a shortcut info in disabled mode for now. info = c.loadSimpleWorkspaceItem(); @@ -843,7 +856,8 @@ public class LoaderTask implements Runnable { return allActivityList; } - private void loadDeepShortcuts() { + private List<ShortcutInfo> loadDeepShortcuts() { + List<ShortcutInfo> allShortcuts = new ArrayList<>(); mBgDataModel.deepShortcutMap.clear(); mBgDataModel.hasShortcutHostPermission = mShortcutManager.hasHostPermission(); if (mBgDataModel.hasShortcutHostPermission) { @@ -851,10 +865,12 @@ public class LoaderTask implements Runnable { if (mUserManager.isUserUnlocked(user)) { List<ShortcutInfo> shortcuts = mShortcutManager.queryForAllShortcuts(user); + allShortcuts.addAll(shortcuts); mBgDataModel.updateDeepShortcutCounts(null, user, shortcuts); } } } + return allShortcuts; } public static boolean isValidProvider(AppWidgetProviderInfo provider) { |