Storing BitmapInfo instead of icon and color directly in itemInfo
This will allow subclassing BitmapInfo to support custom icon/dynamic icons which can be loaded on the background thread instead of going through IconFactory which runs on UiThread Change-Id: Ieced6e91330bdff1b505826d097a8df711dfe967
This commit is contained in:
parent
0d9752c647
commit
3808a69a6c
|
@ -18,32 +18,45 @@ package com.android.launcher3.icons;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class BitmapInfo {
|
||||
|
||||
public static final Bitmap LOW_RES_ICON = Bitmap.createBitmap(1, 1, Config.ALPHA_8);
|
||||
public static final BitmapInfo LOW_RES_INFO = fromBitmap(LOW_RES_ICON, null);
|
||||
|
||||
public Bitmap icon;
|
||||
public int color;
|
||||
public final Bitmap icon;
|
||||
public final int color;
|
||||
|
||||
public void applyTo(BitmapInfo info) {
|
||||
info.icon = icon;
|
||||
info.color = color;
|
||||
public BitmapInfo(Bitmap icon, int color) {
|
||||
this.icon = icon;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ideally icon should not be null, except in cases when generating hardware bitmap failed
|
||||
*/
|
||||
public final boolean isNullOrLowRes() {
|
||||
return icon == null || icon == LOW_RES_ICON;
|
||||
}
|
||||
|
||||
public final boolean isLowRes() {
|
||||
return LOW_RES_ICON == icon;
|
||||
}
|
||||
|
||||
public static BitmapInfo fromBitmap(Bitmap bitmap) {
|
||||
return fromBitmap(bitmap, null);
|
||||
public static BitmapInfo fromBitmap(@NonNull Bitmap bitmap) {
|
||||
return of(bitmap, 0);
|
||||
}
|
||||
|
||||
public static BitmapInfo fromBitmap(Bitmap bitmap, ColorExtractor dominantColorExtractor) {
|
||||
BitmapInfo info = new BitmapInfo();
|
||||
info.icon = bitmap;
|
||||
info.color = dominantColorExtractor != null
|
||||
public static BitmapInfo fromBitmap(@NonNull Bitmap bitmap,
|
||||
@Nullable ColorExtractor dominantColorExtractor) {
|
||||
return of(bitmap, dominantColorExtractor != null
|
||||
? dominantColorExtractor.findDominantColorByHue(bitmap)
|
||||
: 0;
|
||||
return info;
|
||||
: 0);
|
||||
}
|
||||
|
||||
public static BitmapInfo of(@NonNull Bitmap bitmap, int color) {
|
||||
return new BitmapInfo(bitmap, color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,10 @@ public abstract class BaseIconCache {
|
|||
// Empty class name is used for storing package default entry.
|
||||
public static final String EMPTY_CLASS_NAME = ".";
|
||||
|
||||
public static class CacheEntry extends BitmapInfo {
|
||||
public static class CacheEntry {
|
||||
|
||||
@NonNull
|
||||
public BitmapInfo bitmap = BitmapInfo.LOW_RES_INFO;
|
||||
public CharSequence title = "";
|
||||
public CharSequence contentDescription = "";
|
||||
}
|
||||
|
@ -259,23 +262,23 @@ public abstract class BaseIconCache {
|
|||
if (!replaceExisting) {
|
||||
entry = mCache.get(key);
|
||||
// We can't reuse the entry if the high-res icon is not present.
|
||||
if (entry == null || entry.icon == null || entry.isLowRes()) {
|
||||
if (entry == null || entry.bitmap.isNullOrLowRes()) {
|
||||
entry = null;
|
||||
}
|
||||
}
|
||||
if (entry == null) {
|
||||
entry = new CacheEntry();
|
||||
cachingLogic.loadIcon(mContext, object, entry);
|
||||
entry.bitmap = cachingLogic.loadIcon(mContext, object);
|
||||
}
|
||||
// Icon can't be loaded from cachingLogic, which implies alternative icon was loaded
|
||||
// (e.g. fallback icon, default icon). So we drop here since there's no point in caching
|
||||
// an empty entry.
|
||||
if (entry.icon == null) return;
|
||||
if (entry.bitmap.isNullOrLowRes()) return;
|
||||
entry.title = cachingLogic.getLabel(object);
|
||||
entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
|
||||
if (cachingLogic.addToMemCache()) mCache.put(key, entry);
|
||||
|
||||
ContentValues values = newContentValues(entry, entry.title.toString(),
|
||||
ContentValues values = newContentValues(entry.bitmap, entry.title.toString(),
|
||||
componentName.getPackageName(), cachingLogic.getKeywords(object, mLocaleList));
|
||||
addIconToDB(values, componentName, info, userSerial);
|
||||
}
|
||||
|
@ -300,8 +303,8 @@ public abstract class BaseIconCache {
|
|||
return mDefaultIcons.get(user);
|
||||
}
|
||||
|
||||
public boolean isDefaultIcon(Bitmap icon, UserHandle user) {
|
||||
return getDefaultIcon(user).icon == icon;
|
||||
public boolean isDefaultIcon(BitmapInfo icon, UserHandle user) {
|
||||
return getDefaultIcon(user).icon == icon.icon;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -315,7 +318,7 @@ public abstract class BaseIconCache {
|
|||
assertWorkerThread();
|
||||
ComponentKey cacheKey = new ComponentKey(componentName, user);
|
||||
CacheEntry entry = mCache.get(cacheKey);
|
||||
if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
|
||||
if (entry == null || (entry.bitmap.isLowRes() && !useLowResIcon)) {
|
||||
entry = new CacheEntry();
|
||||
if (cachingLogic.addToMemCache()) {
|
||||
mCache.put(cacheKey, entry);
|
||||
|
@ -330,7 +333,7 @@ public abstract class BaseIconCache {
|
|||
providerFetchedOnce = true;
|
||||
|
||||
if (object != null) {
|
||||
cachingLogic.loadIcon(mContext, object, entry);
|
||||
entry.bitmap = cachingLogic.loadIcon(mContext, object);
|
||||
} else {
|
||||
if (usePackageIcon) {
|
||||
CacheEntry packageEntry = getEntryForPackageLocked(
|
||||
|
@ -338,15 +341,15 @@ public abstract class BaseIconCache {
|
|||
if (packageEntry != null) {
|
||||
if (DEBUG) Log.d(TAG, "using package default icon for " +
|
||||
componentName.toShortString());
|
||||
packageEntry.applyTo(entry);
|
||||
entry.bitmap = packageEntry.bitmap;
|
||||
entry.title = packageEntry.title;
|
||||
entry.contentDescription = packageEntry.contentDescription;
|
||||
}
|
||||
}
|
||||
if (entry.icon == null) {
|
||||
if (entry.bitmap == null) {
|
||||
if (DEBUG) Log.d(TAG, "using default icon for " +
|
||||
componentName.toShortString());
|
||||
getDefaultIcon(user).applyTo(entry);
|
||||
entry.bitmap = getDefaultIcon(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -390,10 +393,10 @@ public abstract class BaseIconCache {
|
|||
}
|
||||
if (icon != null) {
|
||||
BaseIconFactory li = getIconFactory();
|
||||
li.createIconBitmap(icon).applyTo(entry);
|
||||
entry.bitmap = li.createIconBitmap(icon);
|
||||
li.close();
|
||||
}
|
||||
if (!TextUtils.isEmpty(title) && entry.icon != null) {
|
||||
if (!TextUtils.isEmpty(title) && entry.bitmap.icon != null) {
|
||||
mCache.put(cacheKey, entry);
|
||||
}
|
||||
}
|
||||
|
@ -413,7 +416,7 @@ public abstract class BaseIconCache {
|
|||
ComponentKey cacheKey = getPackageKey(packageName, user);
|
||||
CacheEntry entry = mCache.get(cacheKey);
|
||||
|
||||
if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
|
||||
if (entry == null || (entry.bitmap.isLowRes() && !useLowResIcon)) {
|
||||
entry = new CacheEntry();
|
||||
boolean entryUpdated = true;
|
||||
|
||||
|
@ -438,8 +441,8 @@ public abstract class BaseIconCache {
|
|||
|
||||
entry.title = appInfo.loadLabel(mPackageManager);
|
||||
entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
|
||||
entry.icon = useLowResIcon ? LOW_RES_ICON : iconInfo.icon;
|
||||
entry.color = iconInfo.color;
|
||||
entry.bitmap = BitmapInfo.of(
|
||||
useLowResIcon ? LOW_RES_ICON : iconInfo.icon, iconInfo.color);
|
||||
|
||||
// Add the icon in the DB here, since these do not get written during
|
||||
// package updates.
|
||||
|
@ -472,7 +475,7 @@ public abstract class BaseIconCache {
|
|||
Long.toString(getSerialNumberForUser(cacheKey.user))});
|
||||
if (c.moveToNext()) {
|
||||
// Set the alpha to be 255, so that we never have a wrong color
|
||||
entry.color = setColorAlphaBound(c.getInt(0), 255);
|
||||
entry.bitmap = BitmapInfo.of(LOW_RES_ICON, setColorAlphaBound(c.getInt(0), 255));
|
||||
entry.title = c.getString(1);
|
||||
if (entry.title == null) {
|
||||
entry.title = "";
|
||||
|
@ -482,13 +485,12 @@ public abstract class BaseIconCache {
|
|||
entry.title, cacheKey.user);
|
||||
}
|
||||
|
||||
if (lowRes) {
|
||||
entry.icon = LOW_RES_ICON;
|
||||
} else {
|
||||
if (!lowRes) {
|
||||
byte[] data = c.getBlob(2);
|
||||
try {
|
||||
entry.icon = BitmapFactory.decodeByteArray(data, 0, data.length,
|
||||
mDecodeOptions);
|
||||
entry.bitmap = BitmapInfo.of(
|
||||
BitmapFactory.decodeByteArray(data, 0, data.length, mDecodeOptions),
|
||||
entry.bitmap.color);
|
||||
} catch (Exception e) { }
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context;
|
|||
import android.os.LocaleList;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
|
@ -32,7 +33,8 @@ public interface CachingLogic<T> {
|
|||
|
||||
CharSequence getLabel(T object);
|
||||
|
||||
void loadIcon(Context context, T object, BitmapInfo target);
|
||||
@NonNull
|
||||
BitmapInfo loadIcon(Context context, T object);
|
||||
|
||||
/**
|
||||
* Provides a option list of keywords to associate with this object
|
||||
|
|
|
@ -170,7 +170,7 @@ public class DynamicItemCache {
|
|||
if (!details.isEmpty()) {
|
||||
WorkspaceItemInfo si = new WorkspaceItemInfo(details.get(0), mContext);
|
||||
try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
|
||||
si.applyFrom(li.createShortcutIcon(details.get(0), true /* badged */, null));
|
||||
si.bitmap = li.createShortcutIcon(details.get(0), true /* badged */, null);
|
||||
} catch (Exception e) {
|
||||
if (DEBUG) {
|
||||
Log.e(TAG, "Error loading shortcut icon for " + shortcutKey.toString());
|
||||
|
@ -209,7 +209,7 @@ public class DynamicItemCache {
|
|||
InstantAppItemInfo info = new InstantAppItemInfo(intent, pkgName);
|
||||
IconCache iconCache = LauncherAppState.getInstance(mContext).getIconCache();
|
||||
iconCache.getTitleAndIcon(info, false);
|
||||
if (info.iconBitmap == null || iconCache.isDefaultIcon(info.iconBitmap, info.user)) {
|
||||
if (info.bitmap.icon == null || iconCache.isDefaultIcon(info.bitmap, info.user)) {
|
||||
return null;
|
||||
}
|
||||
return info;
|
||||
|
|
|
@ -202,15 +202,14 @@ public class BaseModelUpdateTaskTestCase {
|
|||
CacheEntry entry = mCache.get(new ComponentKey(componentName, user));
|
||||
if (entry == null) {
|
||||
entry = new CacheEntry();
|
||||
getDefaultIcon(user).applyTo(entry);
|
||||
entry.bitmap = getDefaultIcon(user);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void addCache(ComponentName key, String title) {
|
||||
CacheEntry entry = new CacheEntry();
|
||||
entry.icon = newIcon();
|
||||
entry.color = Color.RED;
|
||||
entry.bitmap = BitmapInfo.of(newIcon(), Color.RED);
|
||||
entry.title = title;
|
||||
mCache.put(new ComponentKey(key, Process.myUserHandle()), entry);
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ package com.android.launcher3.model;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -43,7 +43,7 @@ public class CacheDataUpdatedTaskTest extends BaseModelUpdateTaskTestCase {
|
|||
public void testCacheUpdate_update_apps() throws Exception {
|
||||
// Clear all icons from apps list so that its easy to check what was updated
|
||||
for (AppInfo info : allAppsList.data) {
|
||||
info.iconBitmap = null;
|
||||
info.bitmap = BitmapInfo.LOW_RES_INFO;
|
||||
}
|
||||
|
||||
executeTaskForTest(newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, "app1"));
|
||||
|
@ -56,9 +56,9 @@ public class CacheDataUpdatedTaskTest extends BaseModelUpdateTaskTestCase {
|
|||
assertFalse(allAppsList.data.isEmpty());
|
||||
for (AppInfo info : allAppsList.data) {
|
||||
if (info.componentName.getPackageName().equals("app1")) {
|
||||
assertNotNull(info.iconBitmap);
|
||||
assertFalse(info.bitmap.isNullOrLowRes());
|
||||
} else {
|
||||
assertNull(info.iconBitmap);
|
||||
assertTrue(info.bitmap.isNullOrLowRes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,10 +85,10 @@ public class CacheDataUpdatedTaskTest extends BaseModelUpdateTaskTestCase {
|
|||
for (ItemInfo info : bgDataModel.itemsIdMap) {
|
||||
if (updates.contains(info.id)) {
|
||||
assertEquals(NEW_LABEL_PREFIX + info.id, info.title);
|
||||
assertNotNull(((WorkspaceItemInfo) info).iconBitmap);
|
||||
assertFalse(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
|
||||
} else {
|
||||
assertNotSame(NEW_LABEL_PREFIX + info.id, info.title);
|
||||
assertNull(((WorkspaceItemInfo) info).iconBitmap);
|
||||
assertTrue(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -289,7 +289,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
private void applyIconAndLabel(ItemInfoWithIcon info) {
|
||||
FastBitmapDrawable iconDrawable = DrawableFactory.INSTANCE.get(getContext())
|
||||
.newIcon(getContext(), info);
|
||||
mDotParams.color = IconPalette.getMutedColor(info.iconColor, 0.54f);
|
||||
mDotParams.color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
|
||||
|
||||
setIcon(iconDrawable);
|
||||
setText(info.title);
|
||||
|
@ -665,7 +665,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
mDisableRelayout = true;
|
||||
|
||||
// Optimization: Starting in N, pre-uploads the bitmap to RenderThread.
|
||||
info.iconBitmap.prepareToDraw();
|
||||
info.bitmap.icon.prepareToDraw();
|
||||
|
||||
if (info instanceof AppInfo) {
|
||||
applyFromApplicationInfo((AppInfo) info);
|
||||
|
|
|
@ -98,10 +98,6 @@ public class FastBitmapDrawable extends Drawable {
|
|||
this(info.icon, info.color);
|
||||
}
|
||||
|
||||
public FastBitmapDrawable(ItemInfoWithIcon info) {
|
||||
this(info.iconBitmap, info.iconColor);
|
||||
}
|
||||
|
||||
protected FastBitmapDrawable(Bitmap b, int iconColor) {
|
||||
this(b, iconColor, false);
|
||||
}
|
||||
|
|
|
@ -485,7 +485,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
|||
} else if (shortcutInfo != null) {
|
||||
WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, mContext);
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
itemInfo.applyFrom(li.createShortcutIcon(shortcutInfo));
|
||||
itemInfo.bitmap = li.createShortcutIcon(shortcutInfo);
|
||||
li.recycle();
|
||||
return Pair.create(itemInfo, shortcutInfo);
|
||||
} else if (providerInfo != null) {
|
||||
|
@ -656,7 +656,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
|||
if (iconInfo == null) {
|
||||
iconInfo = app.getIconCache().getDefaultIcon(info.user);
|
||||
}
|
||||
info.applyFrom(iconInfo);
|
||||
info.bitmap = iconInfo;
|
||||
|
||||
info.title = Utilities.trim(name);
|
||||
info.contentDescription = app.getContext().getPackageManager()
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.icons.BitmapInfo.LOW_RES_ICON;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
|
||||
/**
|
||||
|
@ -30,14 +26,9 @@ public abstract class ItemInfoWithIcon extends ItemInfo {
|
|||
public static final String TAG = "ItemInfoDebug";
|
||||
|
||||
/**
|
||||
* A bitmap version of the application icon.
|
||||
* The bitmap for the application icon
|
||||
*/
|
||||
public Bitmap iconBitmap;
|
||||
|
||||
/**
|
||||
* Dominant color in the {@link #iconBitmap}.
|
||||
*/
|
||||
public int iconColor;
|
||||
public BitmapInfo bitmap = BitmapInfo.LOW_RES_INFO;
|
||||
|
||||
/**
|
||||
* Indicates that the icon is disabled due to safe mode restrictions.
|
||||
|
@ -106,8 +97,7 @@ public abstract class ItemInfoWithIcon extends ItemInfo {
|
|||
|
||||
protected ItemInfoWithIcon(ItemInfoWithIcon info) {
|
||||
super(info);
|
||||
iconBitmap = info.iconBitmap;
|
||||
iconColor = info.iconColor;
|
||||
bitmap = info.bitmap;
|
||||
runtimeStatusFlags = info.runtimeStatusFlags;
|
||||
}
|
||||
|
||||
|
@ -120,12 +110,7 @@ public abstract class ItemInfoWithIcon extends ItemInfo {
|
|||
* Indicates whether we're using a low res icon
|
||||
*/
|
||||
public boolean usingLowResIcon() {
|
||||
return iconBitmap == LOW_RES_ICON;
|
||||
}
|
||||
|
||||
public void applyFrom(BitmapInfo info) {
|
||||
iconBitmap = info.icon;
|
||||
iconColor = info.color;
|
||||
return bitmap.isLowRes();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -510,7 +510,7 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
|
|||
updateAndBindWorkspaceItem(() -> {
|
||||
si.updateFromDeepShortcutInfo(info, mApp.getContext());
|
||||
LauncherIcons li = LauncherIcons.obtain(mApp.getContext());
|
||||
si.applyFrom(li.createShortcutIcon(info));
|
||||
si.bitmap = li.createShortcutIcon(info);
|
||||
li.recycle();
|
||||
return si;
|
||||
});
|
||||
|
@ -546,7 +546,8 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
|
|||
if (args.length > 0 && TextUtils.equals(args[0], "--all")) {
|
||||
writer.println(prefix + "All apps list: size=" + mBgAllAppsList.data.size());
|
||||
for (AppInfo info : mBgAllAppsList.data) {
|
||||
writer.println(prefix + " title=\"" + info.title + "\" iconBitmap=" + info.iconBitmap
|
||||
writer.println(prefix + " title=\"" + info.title
|
||||
+ "\" bitmapIcon=" + info.bitmap.icon
|
||||
+ " componentName=" + info.componentName.getPackageName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -582,7 +582,7 @@ public final class Utilities {
|
|||
}
|
||||
ShortcutInfo si = (ShortcutInfo) obj;
|
||||
LauncherIcons li = LauncherIcons.obtain(appState.getContext());
|
||||
Bitmap badge = li.getShortcutInfoBadge(si, appState.getIconCache()).iconBitmap;
|
||||
Bitmap badge = li.getShortcutInfoBadge(si, appState.getIconCache()).bitmap.icon;
|
||||
li.recycle();
|
||||
float badgeSize = iconSize * LauncherIcons.getBadgeSizeForIconSize(iconSize);
|
||||
float insetFraction = (iconSize - badgeSize) / iconSize;
|
||||
|
|
|
@ -140,7 +140,7 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
|
|||
.put(Favorites.RESTORED, status);
|
||||
|
||||
if (!usingLowResIcon()) {
|
||||
writer.putIcon(iconBitmap, user);
|
||||
writer.putIcon(bitmap, user);
|
||||
}
|
||||
if (iconResource != null) {
|
||||
writer.put(Favorites.ICON_PACKAGE, iconResource.packageName)
|
||||
|
|
|
@ -57,8 +57,8 @@ public class DrawableFactory implements ResourceBasedOverride {
|
|||
*/
|
||||
public FastBitmapDrawable newIcon(Context context, ItemInfoWithIcon info) {
|
||||
FastBitmapDrawable drawable = info.usingLowResIcon()
|
||||
? new PlaceHolderIconDrawable(info, getShapePath(), context)
|
||||
: new FastBitmapDrawable(info);
|
||||
? new PlaceHolderIconDrawable(info.bitmap, getShapePath(), context)
|
||||
: new FastBitmapDrawable(info.bitmap);
|
||||
drawable.setIsDisabled(info.isDisabled());
|
||||
return drawable;
|
||||
}
|
||||
|
|
|
@ -50,8 +50,8 @@ import com.android.launcher3.InsettableFrameLayout;
|
|||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.WorkspaceLayoutManager;
|
||||
import com.android.launcher3.allapps.SearchUiManager;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
|
@ -105,7 +105,7 @@ public class LauncherPreviewRenderer implements Callable<Bitmap> {
|
|||
Build.VERSION.SDK_INT);
|
||||
|
||||
mWorkspaceItemInfo = new WorkspaceItemInfo();
|
||||
mWorkspaceItemInfo.applyFrom(iconInfo);
|
||||
mWorkspaceItemInfo.bitmap = iconInfo;
|
||||
mWorkspaceItemInfo.intent = new Intent();
|
||||
mWorkspaceItemInfo.contentDescription = mWorkspaceItemInfo.title =
|
||||
context.getString(R.string.label_application);
|
||||
|
|
|
@ -24,7 +24,6 @@ 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.icons.BitmapInfo;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
@ -41,10 +40,6 @@ public class PlaceHolderIconDrawable extends FastBitmapDrawable {
|
|||
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);
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ public class PreloadIconDrawable extends FastBitmapDrawable {
|
|||
* @param progressPath fixed path in the bounds [0, 0, 100, 100] representing a progress bar.
|
||||
*/
|
||||
public PreloadIconDrawable(ItemInfoWithIcon info, Path progressPath, Context context) {
|
||||
super(info);
|
||||
super(info.bitmap);
|
||||
mItem = info;
|
||||
mProgressPath = progressPath;
|
||||
mScaledTrackPath = new Path();
|
||||
|
|
|
@ -57,10 +57,8 @@ public interface ComponentWithLabel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void loadIcon(Context context,
|
||||
ComponentWithLabel object, BitmapInfo target) {
|
||||
// Do not load icon.
|
||||
target.icon = BitmapInfo.LOW_RES_ICON;
|
||||
public BitmapInfo loadIcon(Context context, ComponentWithLabel object) {
|
||||
return BitmapInfo.LOW_RES_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -161,7 +161,7 @@ public class IconCache extends BaseIconCache {
|
|||
CacheEntry entry = cacheLocked(application.componentName,
|
||||
application.user, () -> null, mLauncherActivityInfoCachingLogic,
|
||||
false, application.usingLowResIcon());
|
||||
if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) {
|
||||
if (entry.bitmap != null && !isDefaultIcon(entry.bitmap, application.user)) {
|
||||
applyCacheEntry(entry, application);
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ public class IconCache extends BaseIconCache {
|
|||
// null info means not installed, but if we have a component from the intent then
|
||||
// we should still look in the cache for restored app icons.
|
||||
if (info.getTargetComponent() == null) {
|
||||
info.applyFrom(getDefaultIcon(info.user));
|
||||
info.bitmap = getDefaultIcon(info.user);
|
||||
info.title = "";
|
||||
info.contentDescription = "";
|
||||
} else {
|
||||
|
@ -226,7 +226,7 @@ public class IconCache extends BaseIconCache {
|
|||
protected void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
|
||||
info.title = Utilities.trim(entry.title);
|
||||
info.contentDescription = entry.contentDescription;
|
||||
info.applyFrom((entry.icon == null) ? getDefaultIcon(info.user) : entry);
|
||||
info.bitmap = (entry.bitmap == null) ? getDefaultIcon(info.user) : entry.bitmap;
|
||||
}
|
||||
|
||||
public Drawable getFullResIcon(LauncherActivityInfo info) {
|
||||
|
|
|
@ -55,13 +55,12 @@ public class LauncherActivityCachingLogic
|
|||
}
|
||||
|
||||
@Override
|
||||
public void loadIcon(Context context, LauncherActivityInfo object,
|
||||
BitmapInfo target) {
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
li.createBadgedIconBitmap(
|
||||
IconProvider.INSTANCE.get(context)
|
||||
.getIcon(object, li.mFillResIconDpi, true /* flattenDrawable */),
|
||||
object.getUser(), object.getApplicationInfo().targetSdkVersion).applyTo(target);
|
||||
li.recycle();
|
||||
public BitmapInfo loadIcon(Context context, LauncherActivityInfo object) {
|
||||
try (LauncherIcons li = LauncherIcons.obtain(context)) {
|
||||
return li.createBadgedIconBitmap(
|
||||
IconProvider.INSTANCE.get(context)
|
||||
.getIcon(object, li.mFillResIconDpi, true /* flattenDrawable */),
|
||||
object.getUser(), object.getApplicationInfo().targetSdkVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,32 +137,25 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable {
|
|||
if (fallbackIconProvider != null) {
|
||||
// Fallback icons are already badged and with appropriate shadow
|
||||
ItemInfoWithIcon fullIcon = fallbackIconProvider.get();
|
||||
if (fullIcon != null && fullIcon.iconBitmap != null) {
|
||||
BitmapInfo result = new BitmapInfo();
|
||||
result.icon = fullIcon.iconBitmap;
|
||||
result.color = fullIcon.iconColor;
|
||||
return result;
|
||||
if (fullIcon != null && fullIcon.bitmap != null) {
|
||||
return fullIcon.bitmap;
|
||||
}
|
||||
}
|
||||
unbadgedBitmap = cache.getDefaultIcon(Process.myUserHandle()).icon;
|
||||
}
|
||||
|
||||
BitmapInfo result = new BitmapInfo();
|
||||
if (!badged) {
|
||||
result.color = Themes.getColorAccent(mContext);
|
||||
result.icon = unbadgedBitmap;
|
||||
return result;
|
||||
return BitmapInfo.of(unbadgedBitmap, Themes.getColorAccent(mContext));
|
||||
}
|
||||
|
||||
final Bitmap unbadgedfinal = unbadgedBitmap;
|
||||
final ItemInfoWithIcon badge = getShortcutInfoBadge(shortcutInfo, cache);
|
||||
|
||||
result.color = badge.iconColor;
|
||||
result.icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> {
|
||||
Bitmap icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> {
|
||||
getShadowGenerator().recreateIcon(unbadgedfinal, c);
|
||||
badgeWithDrawable(c, new FastBitmapDrawable(badge));
|
||||
badgeWithDrawable(c, new FastBitmapDrawable(badge.bitmap));
|
||||
});
|
||||
return result;
|
||||
return BitmapInfo.of(icon, badge.bitmap.color);
|
||||
}
|
||||
|
||||
public ItemInfoWithIcon getShortcutInfoBadge(ShortcutInfo shortcutInfo, IconCache cache) {
|
||||
|
|
|
@ -137,7 +137,7 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
|
|||
.makeWorkspaceItem();
|
||||
WorkspaceItemInfo wii = (WorkspaceItemInfo) itemInfo;
|
||||
wii.title = "";
|
||||
wii.applyFrom(app.getIconCache().getDefaultIcon(item.user));
|
||||
wii.bitmap = app.getIconCache().getDefaultIcon(item.user);
|
||||
app.getIconCache().getTitleAndIcon(wii,
|
||||
((WorkspaceItemInfo) itemInfo).usingLowResIcon());
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ public class LoaderCursor extends CursorWrapper {
|
|||
info.title = getTitle();
|
||||
// the fallback icon
|
||||
if (!loadIcon(info)) {
|
||||
info.applyFrom(mIconCache.getDefaultIcon(info.user));
|
||||
info.bitmap = mIconCache.getDefaultIcon(info.user);
|
||||
}
|
||||
|
||||
// TODO: If there's an explicit component and we can't install that, delete it.
|
||||
|
@ -183,7 +183,7 @@ public class LoaderCursor extends CursorWrapper {
|
|||
info.iconResource.resourceName = resourceName;
|
||||
BitmapInfo iconInfo = li.createIconBitmap(info.iconResource);
|
||||
if (iconInfo != null) {
|
||||
info.applyFrom(iconInfo);
|
||||
info.bitmap = iconInfo;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ public class LoaderCursor extends CursorWrapper {
|
|||
// Failed to load from resource, try loading from DB.
|
||||
byte[] data = getBlob(iconIndex);
|
||||
try {
|
||||
info.applyFrom(li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length)));
|
||||
info.bitmap = li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to decode byte array for info " + info, e);
|
||||
|
@ -273,7 +273,7 @@ public class LoaderCursor extends CursorWrapper {
|
|||
info.intent = newIntent;
|
||||
|
||||
mIconCache.getTitleAndIcon(info, lai, useLowResIcon);
|
||||
if (mIconCache.isDefaultIcon(info.iconBitmap, user)) {
|
||||
if (mIconCache.isDefaultIcon(info.bitmap, user)) {
|
||||
loadIcon(info);
|
||||
}
|
||||
|
||||
|
|
|
@ -503,8 +503,9 @@ public class LoaderTask implements Runnable {
|
|||
// use the last saved icon instead of the default.
|
||||
Supplier<ItemInfoWithIcon> fallbackIconProvider = () ->
|
||||
c.loadIcon(finalInfo, li) ? finalInfo : null;
|
||||
info.applyFrom(li.createShortcutIcon(pinnedShortcut,
|
||||
true /* badged */, fallbackIconProvider));
|
||||
info.bitmap = li.createShortcutIcon(
|
||||
pinnedShortcut, true /* badged */,
|
||||
fallbackIconProvider);
|
||||
li.recycle();
|
||||
if (pmHelper.isAppSuspended(
|
||||
pinnedShortcut.getPackage(), info.user)) {
|
||||
|
|
|
@ -189,7 +189,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
BitmapInfo iconInfo = li.createIconBitmap(si.iconResource);
|
||||
li.recycle();
|
||||
if (iconInfo != null) {
|
||||
si.applyFrom(iconInfo);
|
||||
si.bitmap = iconInfo;
|
||||
infoUpdated = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,8 +93,8 @@ public class ShortcutsChangedTask extends BaseModelUpdateTask {
|
|||
// If the shortcut is pinned but no longer has an icon in the system,
|
||||
// keep the current icon instead of reverting to the default icon.
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
workspaceItemInfo.applyFrom(li.createShortcutIcon(fullDetails, true,
|
||||
() -> workspaceItemInfo));
|
||||
workspaceItemInfo.bitmap = li.createShortcutIcon(
|
||||
fullDetails, true, () -> workspaceItemInfo);
|
||||
li.recycle();
|
||||
updatedWorkspaceItemInfos.add(workspaceItemInfo);
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask {
|
|||
// If the shortcut is pinned but no longer has an icon in the system,
|
||||
// keep the current icon instead of reverting to the default icon.
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
si.applyFrom(li.createShortcutIcon(shortcut, true, () -> si));
|
||||
si.bitmap = li.createShortcutIcon(shortcut, true, () -> si);
|
||||
li.recycle();
|
||||
} else {
|
||||
si.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
|
||||
|
|
|
@ -82,7 +82,7 @@ public class PinRequestHelper {
|
|||
WorkspaceItemInfo info = new WorkspaceItemInfo(si, context);
|
||||
// Apply the unbadged icon and fetch the actual icon asynchronously.
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
info.applyFrom(li.createShortcutIcon(si, false /* badged */));
|
||||
info.bitmap = li.createShortcutIcon(si, false /* badged */);
|
||||
li.recycle();
|
||||
LauncherAppState.getInstance(context).getModel()
|
||||
.updateAndBindWorkspaceItem(info, si);
|
||||
|
|
|
@ -507,7 +507,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
|
|||
DotInfo dotInfo = mLauncher.getDotInfoForItem(itemInfo);
|
||||
if (mNotificationItemView != null && dotInfo != null) {
|
||||
mNotificationItemView.updateHeader(
|
||||
dotInfo.getNotificationCount(), itemInfo.iconColor);
|
||||
dotInfo.getNotificationCount(), itemInfo.bitmap.color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ public class PopupPopulator {
|
|||
final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, launcher);
|
||||
// Use unbadged icon for the menu.
|
||||
LauncherIcons li = LauncherIcons.obtain(launcher);
|
||||
si.applyFrom(li.createShortcutIcon(shortcut, false /* badged */));
|
||||
si.bitmap = li.createShortcutIcon(shortcut, false /* badged */);
|
||||
li.recycle();
|
||||
si.rank = i;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import android.os.UserHandle;
|
|||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.GraphicsUtils;
|
||||
|
||||
/**
|
||||
|
@ -37,7 +38,7 @@ public class ContentWriter {
|
|||
private final Context mContext;
|
||||
|
||||
private CommitParams mCommitParams;
|
||||
private Bitmap mIcon;
|
||||
private BitmapInfo mIcon;
|
||||
private UserHandle mUser;
|
||||
|
||||
public ContentWriter(Context context, CommitParams commitParams) {
|
||||
|
@ -79,7 +80,7 @@ public class ContentWriter {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ContentWriter putIcon(Bitmap value, UserHandle user) {
|
||||
public ContentWriter putIcon(BitmapInfo value, UserHandle user) {
|
||||
mIcon = value;
|
||||
mUser = user;
|
||||
return this;
|
||||
|
@ -97,7 +98,7 @@ public class ContentWriter {
|
|||
Preconditions.assertNonUiThread();
|
||||
if (mIcon != null && !LauncherAppState.getInstance(context).getIconCache()
|
||||
.isDefaultIcon(mIcon, mUser)) {
|
||||
mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(mIcon));
|
||||
mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(mIcon.icon));
|
||||
mIcon = null;
|
||||
}
|
||||
return mValues;
|
||||
|
|
|
@ -33,12 +33,12 @@ import android.view.View.OnClickListener;
|
|||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.ItemInfoWithIcon;
|
||||
import com.android.launcher3.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.graphics.DrawableFactory;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
@ -128,7 +128,7 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
|||
mCenterDrawable.setCallback(null);
|
||||
mCenterDrawable = null;
|
||||
}
|
||||
if (info.iconBitmap != null) {
|
||||
if (info.bitmap.icon != null) {
|
||||
// The view displays three modes,
|
||||
// 1) App icon in the center
|
||||
// 2) Preload icon in the center
|
||||
|
@ -142,7 +142,7 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
|||
} else if (isReadyForClickSetup()) {
|
||||
mCenterDrawable = drawableFactory.newIcon(getContext(), info);
|
||||
mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate();
|
||||
updateSettingColor(info.iconColor);
|
||||
updateSettingColor(info.bitmap.color);
|
||||
} else {
|
||||
mCenterDrawable = DrawableFactory.INSTANCE.get(getContext())
|
||||
.newPendingIcon(getContext(), info);
|
||||
|
|
|
@ -18,6 +18,8 @@ package com.android.launcher3.widget;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.widget.WidgetsListAdapter.WidgetListRowEntryComparator;
|
||||
|
@ -25,8 +27,6 @@ import com.android.launcher3.widget.WidgetsListAdapter.WidgetListRowEntryCompara
|
|||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* Do diff on widget's tray list items and call the {@link RecyclerView.Adapter}
|
||||
* methods accordingly.
|
||||
|
@ -137,7 +137,7 @@ public class WidgetsDiffReporter {
|
|||
}
|
||||
|
||||
private boolean isSamePackageItemInfo(PackageItemInfo curInfo, PackageItemInfo newInfo) {
|
||||
return curInfo.iconBitmap.equals(newInfo.iconBitmap) &&
|
||||
!mIconCache.isDefaultIcon(curInfo.iconBitmap, curInfo.user);
|
||||
return curInfo.bitmap.icon.equals(newInfo.bitmap.icon)
|
||||
&& !mIconCache.isDefaultIcon(curInfo.bitmap, curInfo.user);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ public class LoaderCursorTest {
|
|||
when(mMockIconCache.getDefaultIcon(eq(mLoaderCursor.user)))
|
||||
.thenReturn(BitmapInfo.fromBitmap(icon));
|
||||
WorkspaceItemInfo info = mLoaderCursor.loadSimpleWorkspaceItem();
|
||||
assertEquals(icon, info.iconBitmap);
|
||||
assertEquals(icon, info.bitmap.icon);
|
||||
assertEquals("my-shortcut", info.title);
|
||||
assertEquals(ITEM_TYPE_SHORTCUT, info.itemType);
|
||||
}
|
||||
|
|
|
@ -23,16 +23,19 @@ import static org.mockito.Mockito.verify;
|
|||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.WidgetPreviewLoader;
|
||||
import com.android.launcher3.compat.AppWidgetManagerCompat;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
import com.android.launcher3.util.MultiHashMap;
|
||||
|
@ -46,8 +49,6 @@ import org.mockito.MockitoAnnotations;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class WidgetsListAdapterTest {
|
||||
|
@ -136,7 +137,7 @@ public class WidgetsListAdapterTest {
|
|||
PackageItemInfo pInfo = new PackageItemInfo(wi.componentName.getPackageName());
|
||||
pInfo.title = pInfo.packageName;
|
||||
pInfo.user = wi.user;
|
||||
pInfo.iconBitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8);
|
||||
pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
|
||||
newMap.addToList(pInfo, wi);
|
||||
if (newMap.size() == num) {
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue