Using a placeholder icon shape instead of low-res/blurry icon
Bug: 111142970 Change-Id: I867224464ae9c026f4dcb5256ef14fc39c8e751d
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -853,24 +855,6 @@ public class IconCache {
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.graphics.BitmapInfo.LOW_RES_ICON;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
/**
|
||||
@@ -33,11 +35,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.
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
protected Path getPreloadProgressPath() {
|
||||
if (mPreloadProgressPath != null) {
|
||||
return mPreloadProgressPath;
|
||||
}
|
||||
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);
|
||||
}
|
||||
// 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);
|
||||
mPreloadProgressPath = p;
|
||||
}
|
||||
|
||||
// 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);
|
||||
return mPreloadProgressPath;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user