diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2018-08-20 15:01:03 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2018-08-27 10:43:46 -0700 |
commit | 2b787e5bd6314b3b657b73e529e16cb52863bcbb (patch) | |
tree | 8d546393acb2c6bdf11206b8bb40f942909da80b | |
parent | 018e3c4447ad77344c378bf3cca4a6484fa45a9e (diff) | |
download | android_packages_apps_Trebuchet-2b787e5bd6314b3b657b73e529e16cb52863bcbb.tar.gz android_packages_apps_Trebuchet-2b787e5bd6314b3b657b73e529e16cb52863bcbb.tar.bz2 android_packages_apps_Trebuchet-2b787e5bd6314b3b657b73e529e16cb52863bcbb.zip |
Using a placeholder icon shape instead of low-res/blurry icon
Bug: 111142970
Change-Id: I867224464ae9c026f4dcb5256ef14fc39c8e751d
18 files changed, 179 insertions, 134 deletions
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 37d0b12bd..5680a6709 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -427,8 +427,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag mFloatingView = new View(mLauncher); if (isBubbleTextView && v.getTag() instanceof ItemInfoWithIcon ) { // Create a copy of the app icon - mFloatingView.setBackground( - DrawableFactory.get(mLauncher).newIcon((ItemInfoWithIcon) v.getTag())); + mFloatingView.setBackground(DrawableFactory.INSTANCE.get(mLauncher) + .newIcon(v.getContext(), (ItemInfoWithIcon) v.getTag())); } // Position the floating view exactly on top of the original diff --git a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java index a4a2e5690..8f7dbdd36 100644 --- a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java +++ b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java @@ -49,7 +49,7 @@ public class NormalizedIconLoader extends IconLoader { LruCache<ComponentName, ActivityInfo> activityInfoCache, boolean disableColorExtraction) { super(context, iconCache, activityInfoCache); - mDrawableFactory = DrawableFactory.get(context); + mDrawableFactory = DrawableFactory.INSTANCE.get(context); mDisableColorExtraction = disableColorExtraction; } @@ -96,6 +96,6 @@ public class NormalizedIconLoader extends IconLoader { userId, desc.getPrimaryColor(), activityInfo.applicationInfo.isInstantApp()); - return mDrawableFactory.newIcon(bitmapInfo, activityInfo); + return mDrawableFactory.newIcon(mContext, bitmapInfo, activityInfo); } } diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 045e4e98c..956270cba 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -34,6 +34,7 @@ <attr name="workspaceStatusBarScrim" format="reference" /> <attr name="widgetsTheme" format="reference" /> <attr name="folderBadgeColor" format="color" /> + <attr name="loadingIconColor" format="color" /> <!-- BubbleTextView specific attributes. --> <declare-styleable name="BubbleTextView"> diff --git a/res/values/styles.xml b/res/values/styles.xml index 7ea28ccf0..098aac562 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -43,6 +43,7 @@ <item name="workspaceStatusBarScrim">@drawable/workspace_bg</item> <item name="widgetsTheme">@style/WidgetContainerTheme</item> <item name="folderBadgeColor">?android:attr/colorPrimary</item> + <item name="loadingIconColor">#FFF</item> </style> <style name="LauncherTheme" parent="@style/BaseLauncherThemeWithCustomAttrs"></style> @@ -73,6 +74,7 @@ <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item> <item name="folderBadgeColor">#FF464646</item> <item name="isMainColorDark">true</item> + <item name="loadingIconColor">#000</item> </style> <style name="LauncherTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark"> diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java index 24826918f..45859ca07 100644 --- a/src/com/android/launcher3/AllAppsList.java +++ b/src/com/android/launcher3/AllAppsList.java @@ -92,7 +92,7 @@ public class AllAppsList { // only if not yet installed if (applicationInfo == null) { PromiseAppInfo info = new PromiseAppInfo(installInfo); - mIconCache.getTitleAndIcon(info, info.usingLowResIcon); + mIconCache.getTitleAndIcon(info, info.usingLowResIcon()); data.add(info); added.add(info); } diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 230ea4fea..5d401433b 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -256,7 +256,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } private void applyIconAndLabel(ItemInfoWithIcon info) { - FastBitmapDrawable iconDrawable = DrawableFactory.get(getContext()).newIcon(info); + FastBitmapDrawable iconDrawable = DrawableFactory.INSTANCE.get(getContext()) + .newIcon(getContext(), info); mBadgeColor = IconPalette.getMutedColor(info.iconColor, 0.54f); setIcon(iconDrawable); @@ -527,8 +528,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, preloadDrawable = (PreloadIconDrawable) mIcon; preloadDrawable.setLevel(progressLevel); } else { - preloadDrawable = DrawableFactory.get(getContext()) - .newPendingIcon(info, getContext()); + preloadDrawable = DrawableFactory.INSTANCE.get(getContext()) + .newPendingIcon(getContext(), info); preloadDrawable.setLevel(progressLevel); setIcon(preloadDrawable); } @@ -639,7 +640,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } if (getTag() instanceof ItemInfoWithIcon) { ItemInfoWithIcon info = (ItemInfoWithIcon) getTag(); - if (info.usingLowResIcon) { + if (info.usingLowResIcon()) { mIconLoadRequest = LauncherAppState.getInstance(getContext()).getIconCache() .updateIconInBackground(BubbleTextView.this, info); } diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java index abd5538c6..61fb3e38b 100644 --- a/src/com/android/launcher3/IconCache.java +++ b/src/com/android/launcher3/IconCache.java @@ -16,6 +16,8 @@ package com.android.launcher3; +import static com.android.launcher3.graphics.BitmapInfo.LOW_RES_ICON; + import android.content.ComponentName; import android.content.ContentValues; import android.content.Context; @@ -79,14 +81,15 @@ public class IconCache { private static final boolean DEBUG = false; private static final boolean DEBUG_IGNORE_CACHE = false; - private static final int LOW_RES_SCALE_FACTOR = 5; - @Thunk static final Object ICON_UPDATE_TOKEN = new Object(); public static class CacheEntry extends BitmapInfo { public CharSequence title = ""; public CharSequence contentDescription = ""; - public boolean isLowResIcon; + + public boolean isLowRes() { + return LOW_RES_ICON == icon; + } } private final HashMap<UserHandle, BitmapInfo> mDefaultIcons = new HashMap<>(); @@ -105,8 +108,7 @@ public class IconCache { @Thunk final Handler mWorkerHandler; - private final BitmapFactory.Options mLowResOptions; - private final BitmapFactory.Options mHighResOptions; + private final BitmapFactory.Options mDecodeOptions; private int mPendingIconRequestCount = 0; @@ -122,16 +124,11 @@ public class IconCache { mIconProvider = IconProvider.newInstance(context); mWorkerHandler = new Handler(LauncherModel.getWorkerLooper()); - mLowResOptions = new BitmapFactory.Options(); - // Always prefer RGB_565 config for low res. If the bitmap has transparency, it will - // automatically be loaded as ALPHA_8888. - mLowResOptions.inPreferredConfig = Bitmap.Config.RGB_565; - if (BitmapRenderer.USE_HARDWARE_BITMAP) { - mHighResOptions = new BitmapFactory.Options(); - mHighResOptions.inPreferredConfig = Bitmap.Config.HARDWARE; + mDecodeOptions = new BitmapFactory.Options(); + mDecodeOptions.inPreferredConfig = Bitmap.Config.HARDWARE; } else { - mHighResOptions = null; + mDecodeOptions = null; } } @@ -374,7 +371,7 @@ public class IconCache { if (!replaceExisting) { entry = mCache.get(key); // We can't reuse the entry if the high-res icon is not present. - if (entry == null || entry.isLowResIcon || entry.icon == null) { + if (entry == null || entry.icon == null || entry.isLowRes()) { entry = null; } } @@ -389,8 +386,7 @@ public class IconCache { entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, app.getUser()); mCache.put(key, entry); - Bitmap lowResIcon = generateLowResIcon(entry.icon); - ContentValues values = newContentValues(entry.icon, lowResIcon, entry.color, + ContentValues values = newContentValues(entry.icon, entry.color, entry.title.toString(), app.getApplicationInfo().packageName); addIconToDB(values, app.getComponentName(), info, userSerial); } @@ -451,7 +447,7 @@ public class IconCache { public synchronized void updateTitleAndIcon(AppInfo application) { CacheEntry entry = cacheLocked(application.componentName, Provider.<LauncherActivityInfo>of(null), - application.user, false, application.usingLowResIcon); + application.user, false, application.usingLowResIcon()); if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) { applyCacheEntry(entry, application); } @@ -477,7 +473,6 @@ public class IconCache { getDefaultIcon(info.user).applyTo(info); info.title = ""; info.contentDescription = ""; - info.usingLowResIcon = false; } else { Intent intent = info.getIntent(); getTitleAndIcon(info, () -> mLauncherApps.resolveActivity(intent, info.user), @@ -510,7 +505,6 @@ public class IconCache { private void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) { info.title = Utilities.trim(entry.title); info.contentDescription = entry.contentDescription; - info.usingLowResIcon = entry.isLowResIcon; ((entry.icon == null) ? getDefaultIcon(info.user) : entry).applyTo(info); } @@ -536,7 +530,7 @@ public class IconCache { Preconditions.assertWorkerThread(); ComponentKey cacheKey = new ComponentKey(componentName, user); CacheEntry entry = mCache.get(cacheKey); - if (entry == null || (entry.isLowResIcon && !useLowResIcon)) { + if (entry == null || (entry.isLowRes() && !useLowResIcon)) { entry = new CacheEntry(); mCache.put(cacheKey, entry); @@ -635,7 +629,7 @@ public class IconCache { ComponentKey cacheKey = getPackageKey(packageName, user); CacheEntry entry = mCache.get(cacheKey); - if (entry == null || (entry.isLowResIcon && !useLowResIcon)) { + if (entry == null || (entry.isLowRes() && !useLowResIcon)) { entry = new CacheEntry(); boolean entryUpdated = true; @@ -658,16 +652,14 @@ public class IconCache { mInstantAppResolver.isInstantApp(appInfo)); li.recycle(); - Bitmap lowResIcon = generateLowResIcon(iconInfo.icon); entry.title = appInfo.loadLabel(mPackageManager); entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user); - entry.icon = useLowResIcon ? lowResIcon : iconInfo.icon; + entry.icon = useLowResIcon ? LOW_RES_ICON : iconInfo.icon; entry.color = iconInfo.color; - entry.isLowResIcon = useLowResIcon; // Add the icon in the DB here, since these do not get written during // package updates. - ContentValues values = newContentValues(iconInfo.icon, lowResIcon, entry.color, + ContentValues values = newContentValues(iconInfo.icon, entry.color, entry.title.toString(), packageName); addIconToDB(values, cacheKey.componentName, info, mUserManager.getSerialNumberForUser(user)); @@ -690,17 +682,15 @@ public class IconCache { Cursor c = null; try { c = mIconDb.query( - new String[]{lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON, - IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL}, - IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?", - new String[]{cacheKey.componentName.flattenToString(), - Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))}); + lowRes ? IconDB.COLUMNS_LOW_RES : IconDB.COLUMNS_HIGH_RES, + IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?", + new String[]{ + cacheKey.componentName.flattenToString(), + Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))}); if (c.moveToNext()) { - entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : mHighResOptions); // Set the alpha to be 255, so that we never have a wrong color - entry.color = ColorUtils.setAlphaComponent(c.getInt(1), 255); - entry.isLowResIcon = lowRes; - entry.title = c.getString(2); + entry.color = ColorUtils.setAlphaComponent(c.getInt(0), 255); + entry.title = c.getString(1); if (entry.title == null) { entry.title = ""; entry.contentDescription = ""; @@ -708,6 +698,16 @@ public class IconCache { entry.contentDescription = mUserManager.getBadgedLabelForUser( entry.title, cacheKey.user); } + + if (lowRes) { + entry.icon = LOW_RES_ICON; + } else { + byte[] data = c.getBlob(2); + try { + entry.icon = BitmapFactory.decodeByteArray(data, 0, data.length, + mDecodeOptions); + } catch (Exception e) { } + } return true; } } catch (SQLiteException e) { @@ -803,7 +803,7 @@ public class IconCache { } private static final class IconDB extends SQLiteCacheHelper { - private final static int RELEASE_VERSION = 24; + private final static int RELEASE_VERSION = 25; private final static String TABLE_NAME = "icons"; private final static String COLUMN_ROWID = "rowid"; @@ -812,11 +812,15 @@ public class IconCache { private final static String COLUMN_LAST_UPDATED = "lastUpdated"; private final static String COLUMN_VERSION = "version"; private final static String COLUMN_ICON = "icon"; - private final static String COLUMN_ICON_LOW_RES = "icon_low_res"; private final static String COLUMN_ICON_COLOR = "icon_color"; private final static String COLUMN_LABEL = "label"; private final static String COLUMN_SYSTEM_STATE = "system_state"; + private final static String[] COLUMNS_HIGH_RES = new String[] { + IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL, IconDB.COLUMN_ICON }; + private final static String[] COLUMNS_LOW_RES = new String[] { + IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL }; + public IconDB(Context context, int iconPixelSize) { super(context, LauncherFiles.APP_ICONS_DB, (RELEASE_VERSION << 16) + iconPixelSize, @@ -831,7 +835,6 @@ public class IconCache { COLUMN_LAST_UPDATED + " INTEGER NOT NULL DEFAULT 0, " + COLUMN_VERSION + " INTEGER NOT NULL DEFAULT 0, " + COLUMN_ICON + " BLOB, " + - COLUMN_ICON_LOW_RES + " BLOB, " + COLUMN_ICON_COLOR + " INTEGER NOT NULL DEFAULT 0, " + COLUMN_LABEL + " TEXT, " + COLUMN_SYSTEM_STATE + " TEXT, " + @@ -840,11 +843,10 @@ public class IconCache { } } - private ContentValues newContentValues(Bitmap icon, Bitmap lowResIcon, int iconColor, - String label, String packageName) { + private ContentValues newContentValues(Bitmap icon, int iconColor, String label, + String packageName) { ContentValues values = new ContentValues(); values.put(IconDB.COLUMN_ICON, Utilities.flattenBitmap(icon)); - values.put(IconDB.COLUMN_ICON_LOW_RES, Utilities.flattenBitmap(lowResIcon)); values.put(IconDB.COLUMN_ICON_COLOR, iconColor); values.put(IconDB.COLUMN_LABEL, label); @@ -854,24 +856,6 @@ public class IconCache { } /** - * Generates a new low-res icon given a high-res icon. - */ - private Bitmap generateLowResIcon(Bitmap icon) { - return Bitmap.createScaledBitmap(icon, - icon.getWidth() / LOW_RES_SCALE_FACTOR, - icon.getHeight() / LOW_RES_SCALE_FACTOR, true); - } - - private static Bitmap loadIconNoResize(Cursor c, int iconIndex, BitmapFactory.Options options) { - byte[] data = c.getBlob(iconIndex); - try { - return BitmapFactory.decodeByteArray(data, 0, data.length, options); - } catch (Exception e) { - return null; - } - } - - /** * Interface for receiving itemInfo with high-res icon. */ public interface ItemInfoUpdateReceiver { diff --git a/src/com/android/launcher3/ItemInfoWithIcon.java b/src/com/android/launcher3/ItemInfoWithIcon.java index 4677d3181..2ceb0dd71 100644 --- a/src/com/android/launcher3/ItemInfoWithIcon.java +++ b/src/com/android/launcher3/ItemInfoWithIcon.java @@ -16,6 +16,8 @@ package com.android.launcher3; +import static com.android.launcher3.graphics.BitmapInfo.LOW_RES_ICON; + import android.graphics.Bitmap; /** @@ -34,11 +36,6 @@ public abstract class ItemInfoWithIcon extends ItemInfo { public int iconColor; /** - * Indicates whether we're using a low res icon - */ - public boolean usingLowResIcon; - - /** * Indicates that the icon is disabled due to safe mode restrictions. */ public static final int FLAG_DISABLED_SAFEMODE = 1 << 0; @@ -107,7 +104,6 @@ public abstract class ItemInfoWithIcon extends ItemInfo { super(info); iconBitmap = info.iconBitmap; iconColor = info.iconColor; - usingLowResIcon = info.usingLowResIcon; runtimeStatusFlags = info.runtimeStatusFlags; } @@ -115,4 +111,11 @@ public abstract class ItemInfoWithIcon extends ItemInfo { public boolean isDisabled() { return (runtimeStatusFlags & FLAG_DISABLED_MASK) != 0; } + + /** + * Indicates whether we're using a low res icon + */ + public boolean usingLowResIcon() { + return iconBitmap == LOW_RES_ICON; + } } diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java index 8588c7a92..a84bfd54e 100644 --- a/src/com/android/launcher3/ShortcutInfo.java +++ b/src/com/android/launcher3/ShortcutInfo.java @@ -125,7 +125,7 @@ public class ShortcutInfo extends ItemInfoWithIcon { .put(LauncherSettings.BaseLauncherColumns.INTENT, getIntent()) .put(LauncherSettings.Favorites.RESTORED, status); - if (!usingLowResIcon) { + if (!usingLowResIcon()) { writer.putIcon(iconBitmap, user); } if (iconResource != null) { diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index adc4a72d1..fa07d4d75 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -152,8 +152,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine if (mApps.hasNoFilteredResults()) { if (mEmptySearchBackground == null) { - mEmptySearchBackground = DrawableFactory.get(getContext()) - .getAllAppsBackground(getContext()); + mEmptySearchBackground = new AllAppsBackgroundDrawable(getContext()); mEmptySearchBackground.setAlpha(0); mEmptySearchBackground.setCallback(this); updateEmptySearchBackgroundBounds(); diff --git a/src/com/android/launcher3/graphics/BitmapInfo.java b/src/com/android/launcher3/graphics/BitmapInfo.java index c905a78e5..69c068412 100644 --- a/src/com/android/launcher3/graphics/BitmapInfo.java +++ b/src/com/android/launcher3/graphics/BitmapInfo.java @@ -16,11 +16,14 @@ package com.android.launcher3.graphics; import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; import com.android.launcher3.ItemInfoWithIcon; public class BitmapInfo { + public static final Bitmap LOW_RES_ICON = Bitmap.createBitmap(1, 1, Config.ALPHA_8); + public Bitmap icon; public int color; diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java index 5bc81e69a..8377adff8 100644 --- a/src/com/android/launcher3/graphics/DrawableFactory.java +++ b/src/com/android/launcher3/graphics/DrawableFactory.java @@ -16,6 +16,8 @@ package com.android.launcher3.graphics; +import static com.android.launcher3.graphics.BitmapInfo.LOW_RES_ICON; + import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; @@ -24,18 +26,18 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Path; import android.graphics.Rect; +import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Process; import android.os.UserHandle; import android.util.ArrayMap; -import android.util.Log; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.ItemInfoWithIcon; import com.android.launcher3.R; import com.android.launcher3.Utilities; -import com.android.launcher3.allapps.AllAppsBackgroundDrawable; +import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.ResourceBasedOverride; import androidx.annotation.UiThread; @@ -45,71 +47,65 @@ import androidx.annotation.UiThread; */ public class DrawableFactory implements ResourceBasedOverride { - private static final String TAG = "DrawableFactory"; + public static final MainThreadInitializedObject<DrawableFactory> INSTANCE = + new MainThreadInitializedObject<>(c -> { + DrawableFactory factory = Overrides.getObject(DrawableFactory.class, + c.getApplicationContext(), R.string.drawable_factory_class); + factory.mContext = c; + return factory; + }); - private static DrawableFactory sInstance; - private static final Object LOCK = new Object(); + private Context mContext; private Path mPreloadProgressPath; - public static DrawableFactory get(Context context) { - synchronized (LOCK) { - if (sInstance == null) { - sInstance = Overrides.getObject(DrawableFactory.class, - context.getApplicationContext(), R.string.drawable_factory_class); - } - return sInstance; - } - } - protected final UserHandle mMyUser = Process.myUserHandle(); protected final ArrayMap<UserHandle, Bitmap> mUserBadges = new ArrayMap<>(); /** * Returns a FastBitmapDrawable with the icon. */ - public FastBitmapDrawable newIcon(ItemInfoWithIcon info) { - FastBitmapDrawable drawable = new FastBitmapDrawable(info); + public FastBitmapDrawable newIcon(Context context, ItemInfoWithIcon info) { + FastBitmapDrawable drawable = info.iconBitmap == LOW_RES_ICON + ? new PlaceHolderIconDrawable(info, getPreloadProgressPath(), context) + : new FastBitmapDrawable(info); drawable.setIsDisabled(info.isDisabled()); return drawable; } - public FastBitmapDrawable newIcon(BitmapInfo info, ActivityInfo target) { - return new FastBitmapDrawable(info); + public FastBitmapDrawable newIcon(Context context, BitmapInfo info, ActivityInfo target) { + return info.icon == LOW_RES_ICON + ? new PlaceHolderIconDrawable(info, getPreloadProgressPath(), context) + : new FastBitmapDrawable(info); } /** * Returns a FastBitmapDrawable with the icon. */ - public PreloadIconDrawable newPendingIcon(ItemInfoWithIcon info, Context context) { - if (mPreloadProgressPath == null) { - mPreloadProgressPath = getPreloadProgressPath(context); - } - return new PreloadIconDrawable(info, mPreloadProgressPath, context); + public PreloadIconDrawable newPendingIcon(Context context, ItemInfoWithIcon info) { + return new PreloadIconDrawable(info, getPreloadProgressPath(), context); } - protected Path getPreloadProgressPath(Context context) { - if (Utilities.ATLEAST_OREO) { - try { - // Try to load the path from Mask Icon - Drawable icon = context.getDrawable(R.drawable.adaptive_icon_drawable_wrapper); - icon.setBounds(0, 0, - PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE); - return (Path) icon.getClass().getMethod("getIconMask").invoke(icon); - } catch (Exception e) { - Log.e(TAG, "Error loading mask icon", e); - } + protected Path getPreloadProgressPath() { + if (mPreloadProgressPath != null) { + return mPreloadProgressPath; } + if (Utilities.ATLEAST_OREO) { + // Load the path from Mask Icon + AdaptiveIconDrawable icon = (AdaptiveIconDrawable) + mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper); + icon.setBounds(0, 0, + PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE); + mPreloadProgressPath = icon.getIconMask(); + } else { - // Create a circle static from top center and going clockwise. - Path p = new Path(); - p.moveTo(PreloadIconDrawable.PATH_SIZE / 2, 0); - p.addArc(0, 0, PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE, -90, 360); - return p; - } - - public AllAppsBackgroundDrawable getAllAppsBackground(Context context) { - return new AllAppsBackgroundDrawable(context); + // Create a circle static from top center and going clockwise. + Path p = new Path(); + p.moveTo(PreloadIconDrawable.PATH_SIZE / 2, 0); + p.addArc(0, 0, PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE, -90, 360); + mPreloadProgressPath = p; + } + return mPreloadProgressPath; } /** diff --git a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java new file mode 100644 index 000000000..18efd47b6 --- /dev/null +++ b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 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.graphics; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Path; +import android.graphics.Rect; + +import com.android.launcher3.FastBitmapDrawable; +import com.android.launcher3.ItemInfoWithIcon; +import com.android.launcher3.R; +import com.android.launcher3.util.Themes; + +/** + * Subclass which draws a placeholder icon when the actual icon is not yet loaded + */ +public class PlaceHolderIconDrawable extends FastBitmapDrawable { + + // Path in [0, 100] bounds. + private final Path mProgressPath; + + public PlaceHolderIconDrawable(BitmapInfo info, Path progressPath, Context context) { + this(info.icon, info.color, progressPath, context); + } + + public PlaceHolderIconDrawable(ItemInfoWithIcon info, Path progressPath, Context context) { + this(info.iconBitmap, info.iconColor, progressPath, context); + } + + protected PlaceHolderIconDrawable(Bitmap b, int iconColor, Path progressPath, Context context) { + super(b, iconColor); + + mProgressPath = progressPath; + mPaint.setColor(Themes.getAttrColor(context, R.attr.loadingIconColor)); + } + + @Override + protected void drawInternal(Canvas canvas, Rect bounds) { + int saveCount = canvas.save(); + canvas.translate(bounds.left, bounds.top); + canvas.scale(bounds.width() / 100f, bounds.height() / 100f); + canvas.drawPath(mProgressPath, mPaint); + canvas.restoreToCount(saveCount); + } +} diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java index 0139bd902..54c054276 100644 --- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java +++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java @@ -64,7 +64,7 @@ public class CacheDataUpdatedTask extends BaseModelUpdateTask { if (si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && isValidShortcut(si) && cn != null && mPackages.contains(cn.getPackageName())) { - iconCache.getTitleAndIcon(si, si.usingLowResIcon); + iconCache.getTitleAndIcon(si, si.usingLowResIcon()); updatedShortcuts.add(si); } } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index e82c8f100..85faf4fbc 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -742,7 +742,7 @@ public class LoaderTask implements Runnable { int numItemsInPreview = 0; for (ShortcutInfo info : folder.contents) { - if (info.usingLowResIcon + if (info.usingLowResIcon() && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && verifier.isItemInPreview(info.rank)) { mIconCache.getTitleAndIcon(info, false); diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index 977dcd7d5..ccb1f0959 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -261,7 +261,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { if (isNewApkAvailable && si.itemType == Favorites.ITEM_TYPE_APPLICATION) { - iconCache.getTitleAndIcon(si, si.usingLowResIcon); + iconCache.getTitleAndIcon(si, si.usingLowResIcon()); infoUpdated = true; } diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java index 961799d57..29b4b0ba2 100644 --- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java +++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java @@ -17,7 +17,6 @@ package com.android.launcher3.widget; import android.content.Context; -import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.PorterDuff; @@ -37,15 +36,12 @@ import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.IconCache; import com.android.launcher3.IconCache.ItemInfoUpdateReceiver; import com.android.launcher3.ItemInfoWithIcon; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.R; -import com.android.launcher3.Utilities; import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.model.PackageItemInfo; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.util.Themes; -import com.android.launcher3.widget.LauncherAppWidgetHostView; public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implements OnClickListener, ItemInfoUpdateReceiver { @@ -137,19 +133,19 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView // 1) App icon in the center // 2) Preload icon in the center // 3) Setup icon in the center and app icon in the top right corner. - DrawableFactory drawableFactory = DrawableFactory.get(getContext()); + DrawableFactory drawableFactory = DrawableFactory.INSTANCE.get(getContext()); if (mDisabledForSafeMode) { - FastBitmapDrawable disabledIcon = drawableFactory.newIcon(info); + FastBitmapDrawable disabledIcon = drawableFactory.newIcon(getContext(), info); disabledIcon.setIsDisabled(true); mCenterDrawable = disabledIcon; mSettingIconDrawable = null; } else if (isReadyForClickSetup()) { - mCenterDrawable = drawableFactory.newIcon(info); + mCenterDrawable = drawableFactory.newIcon(getContext(), info); mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate(); updateSettingColor(info.iconColor); } else { - mCenterDrawable = DrawableFactory.get(getContext()) - .newPendingIcon(info, getContext()); + mCenterDrawable = DrawableFactory.INSTANCE.get(getContext()) + .newPendingIcon(getContext(), info); mSettingIconDrawable = null; applyState(); } diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index 2ba55ab97..66af43aeb 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -179,8 +179,8 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { return; } if (bitmap != null) { - mWidgetImage.setBitmap(bitmap, - DrawableFactory.get(getContext()).getBadgeForUser(mItem.user, getContext())); + mWidgetImage.setBitmap(bitmap, DrawableFactory.INSTANCE.get(getContext()) + .getBadgeForUser(mItem.user, getContext())); if (mAnimatePreview) { mWidgetImage.setAlpha(0f); ViewPropertyAnimator anim = mWidgetImage.animate(); |