Setup make icon-loader library

Bug: 115891474

Test: make -j10 icon-loader
Next step: Launcher will depend on icon-loader in next CL

Change-Id: I797ddb857cf8be79f3be6ca2f174c593ca3713a5
This commit is contained in:
Hyunyoung Song
2018-10-18 15:05:45 -07:00
parent 6083c63e81
commit cda96a5b43
18 changed files with 70 additions and 56 deletions

View File

@@ -28,3 +28,23 @@ java_library_static {
],
platform_apis: true,
}
android_library {
name: "icon-loader",
sdk_version: "28",
static_libs: [
"androidx.core_core",
],
resource_dirs: [
"res",
],
srcs: [
"src/com/android/launcher3/icons/BaseIconFactory.java",
"src/com/android/launcher3/icons/BitmapInfo.java",
"src/com/android/launcher3/icons/IconNormalizer.java",
"src/com/android/launcher3/icons/FixedScaleDrawable.java",
"src/com/android/launcher3/icons/ShadowGenerator.java",
"src/com/android/launcher3/icons/ColorExtractor.java",
],
}

View File

@@ -480,7 +480,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
final LauncherAppState app = LauncherAppState.getInstance(mContext);
// Set default values until proper values is loaded.
appInfo.title = "";
app.getIconCache().getDefaultIcon(user).applyTo(appInfo);
appInfo.applyFrom(app.getIconCache().getDefaultIcon(user));
final ShortcutInfo si = appInfo.makeShortcut();
if (Looper.myLooper() == LauncherModel.getWorkerLooper()) {
app.getIconCache().getTitleAndIcon(si, activityInfo, false /* useLowResIcon */);
@@ -495,7 +495,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
} else if (shortcutInfo != null) {
ShortcutInfo si = new ShortcutInfo(shortcutInfo, mContext);
LauncherIcons li = LauncherIcons.obtain(mContext);
li.createShortcutIcon(shortcutInfo).applyTo(si);
si.applyFrom(li.createShortcutIcon(shortcutInfo));
li.recycle();
return Pair.create((ItemInfo) si, (Object) shortcutInfo);
} else if (providerInfo != null) {
@@ -656,7 +656,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
if (iconInfo == null) {
iconInfo = app.getIconCache().getDefaultIcon(info.user);
}
iconInfo.applyTo(info);
info.applyFrom(iconInfo);
info.title = Utilities.trim(name);
info.contentDescription = UserManagerCompat.getInstance(app.getContext())

View File

@@ -20,6 +20,8 @@ import static com.android.launcher3.icons.BitmapInfo.LOW_RES_ICON;
import android.graphics.Bitmap;
import com.android.launcher3.icons.BitmapInfo;
/**
* Represents an ItemInfo which also holds an icon.
*/
@@ -118,4 +120,10 @@ public abstract class ItemInfoWithIcon extends ItemInfo {
public boolean usingLowResIcon() {
return iconBitmap == LOW_RES_ICON;
}
public void applyFrom(BitmapInfo info) {
iconBitmap = info.icon;
iconColor = info.color;
}
}

View File

@@ -657,7 +657,7 @@ public class LauncherModel extends BroadcastReceiver
updateAndBindShortcutInfo(() -> {
si.updateFromDeepShortcutInfo(info, mApp.getContext());
LauncherIcons li = LauncherIcons.obtain(mApp.getContext());
li.createShortcutIcon(info).applyTo(si);
si.applyFrom(li.createShortcutIcon(info));
li.recycle();
return si;
});

View File

@@ -139,7 +139,7 @@ public class LauncherAppsCompatVO extends LauncherAppsCompatVL {
ShortcutInfo info = new ShortcutInfo(compat, context);
// Apply the unbadged icon and fetch the actual icon asynchronously.
LauncherIcons li = LauncherIcons.obtain(context);
li.createShortcutIcon(compat, false /* badged */).applyTo(info);
info.applyFrom(li.createShortcutIcon(compat, false /* badged */));
li.recycle();
LauncherAppState.getInstance(context).getModel()
.updateAndBindShortcutInfo(info, compat);

View File

@@ -204,7 +204,7 @@ public class DragView extends View {
public void run() {
LauncherAppState appState = LauncherAppState.getInstance(mLauncher);
Object[] outObj = new Object[1];
final Drawable dr = getFullDrawable(info, appState, outObj);
Drawable dr = getFullDrawable(info, appState, outObj);
if (dr instanceof AdaptiveIconDrawable) {
int w = mBitmap.getWidth();
@@ -220,10 +220,20 @@ public class DragView extends View {
mBadge = getBadge(info, appState, outObj[0]);
mBadge.setBounds(badgeBounds);
LauncherIcons li = LauncherIcons.obtain(mLauncher);
Utilities.scaleRectAboutCenter(bounds,
li.getNormalizer().getScale(dr, null, null, null));
li.recycle();
// Do not draw the background in case of folder as its translucent
mDrawBitmap = !(dr instanceof FolderAdaptiveIcon);
try (LauncherIcons li = LauncherIcons.obtain(mLauncher)) {
Drawable nDr; // drawable to be normalized
if (mDrawBitmap) {
nDr = dr;
} else {
// Since we just want the scale, avoid heavy drawing operations
nDr = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
}
Utilities.scaleRectAboutCenter(bounds,
li.getNormalizer().getScale(nDr, null, null, null));
}
AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
// Shrink very tiny bit so that the clip path is smaller than the original bitmap
@@ -259,9 +269,6 @@ public class DragView extends View {
// Assign the variable on the UI thread to avoid race conditions.
mScaledMaskPath = mask;
// Do not draw the background in case of folder as its translucent
mDrawBitmap = !(dr instanceof FolderAdaptiveIcon);
if (info.isDisabled()) {
FastBitmapDrawable d = new FastBitmapDrawable((Bitmap) null);
d.setIsDisabled(true);

View File

@@ -261,7 +261,7 @@ public class BaseIconCache {
protected void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
info.title = Utilities.trim(entry.title);
info.contentDescription = entry.contentDescription;
((entry.icon == null) ? getDefaultIcon(info.user) : entry).applyTo(info);
info.applyFrom((entry.icon == null) ? getDefaultIcon(info.user) : entry);
}
public synchronized BitmapInfo getDefaultIcon(UserHandle user) {

View File

@@ -69,14 +69,14 @@ public class BaseIconFactory {
public ShadowGenerator getShadowGenerator() {
if (mShadowGenerator == null) {
mShadowGenerator = new ShadowGenerator(mContext);
mShadowGenerator = new ShadowGenerator(mIconBitmapSize);
}
return mShadowGenerator;
}
public IconNormalizer getNormalizer() {
if (mNormalizer == null) {
mNormalizer = new IconNormalizer(mContext);
mNormalizer = new IconNormalizer(mContext, mIconBitmapSize);
}
return mNormalizer;
}

View File

@@ -18,8 +18,6 @@ package com.android.launcher3.icons;
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);
@@ -27,11 +25,6 @@ public class BitmapInfo {
public Bitmap icon;
public int color;
public void applyTo(ItemInfoWithIcon info) {
info.iconBitmap = icon;
info.iconColor = color;
}
public void applyTo(BitmapInfo info) {
info.icon = icon;
info.color = color;

View File

@@ -139,7 +139,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) {
getDefaultIcon(info.user).applyTo(info);
info.applyFrom(getDefaultIcon(info.user));
info.title = "";
info.contentDescription = "";
} else {

View File

@@ -28,14 +28,9 @@ import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import java.nio.ByteBuffer;
import androidx.annotation.NonNull;
@@ -84,9 +79,9 @@ public class IconNormalizer {
private final Matrix mMatrix;
/** package private **/
IconNormalizer(Context context) {
IconNormalizer(Context context, int iconBitmapSize) {
// Use twice the icon size as maximum size to avoid scaling down twice.
mMaxSize = LauncherAppState.getIDP(context).iconBitmapSize * 2;
mMaxSize = iconBitmapSize * 2;
mBitmap = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ALPHA_8);
mCanvas = new Canvas(mBitmap);
mPixels = new byte[mMaxSize * mMaxSize];
@@ -193,17 +188,13 @@ public class IconNormalizer {
*/
public synchronized float getScale(@NonNull Drawable d, @Nullable RectF outBounds,
@Nullable Path path, @Nullable boolean[] outMaskShape) {
if (Utilities.ATLEAST_OREO && d instanceof AdaptiveIconDrawable) {
if (BaseIconFactory.ATLEAST_OREO && d instanceof AdaptiveIconDrawable) {
if (mAdaptiveIconScale != SCALE_NOT_INITIALIZED) {
if (outBounds != null) {
outBounds.set(mAdaptiveIconBounds);
}
return mAdaptiveIconScale;
}
if (d instanceof FolderAdaptiveIcon) {
// Since we just want the scale, avoid heavy drawing operations
d = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
}
}
int width = d.getIntrinsicWidth();
int height = d.getIntrinsicHeight();
@@ -314,7 +305,7 @@ public class IconNormalizer {
float areaScale = area / (width * height);
// Use sqrt of the final ratio as the images is scaled across both width and height.
float scale = areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1;
if (Utilities.ATLEAST_OREO && d instanceof AdaptiveIconDrawable &&
if (BaseIconFactory.ATLEAST_OREO && d instanceof AdaptiveIconDrawable &&
mAdaptiveIconScale == SCALE_NOT_INITIALIZED) {
mAdaptiveIconScale = scale;
mAdaptiveIconBounds.set(mBounds);

View File

@@ -16,7 +16,6 @@
package com.android.launcher3.icons;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BlurMaskFilter;
@@ -28,23 +27,19 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import com.android.launcher3.LauncherAppState;
import androidx.core.graphics.ColorUtils;
/**
* Utility class to add shadows to bitmaps.
*/
public class ShadowGenerator {
// Percent of actual icon size
private static final float HALF_DISTANCE = 0.5f;
public static final float BLUR_FACTOR = 0.5f/48;
// Percent of actual icon size
public static final float KEY_SHADOW_DISTANCE = 1f/48;
private static final int KEY_SHADOW_ALPHA = 61;
// Percent of actual icon size
private static final float HALF_DISTANCE = 0.5f;
private static final int AMBIENT_SHADOW_ALPHA = 30;
private final int mIconSize;
@@ -53,8 +48,8 @@ public class ShadowGenerator {
private final Paint mDrawPaint;
private final BlurMaskFilter mDefaultBlurMaskFilter;
public ShadowGenerator(Context context) {
mIconSize = LauncherAppState.getIDP(context).iconBitmapSize;
public ShadowGenerator(int iconSize) {
mIconSize = iconSize;
mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
mDefaultBlurMaskFilter = new BlurMaskFilter(mIconSize * BLUR_FACTOR, Blur.NORMAL);

View File

@@ -153,7 +153,7 @@ public class LoaderCursor extends CursorWrapper {
info.title = getTitle();
// the fallback icon
if (!loadIcon(info)) {
mIconCache.getDefaultIcon(info.user).applyTo(info);
info.applyFrom(mIconCache.getDefaultIcon(info.user));
}
// TODO: If there's an explicit component and we can't install that, delete it.
@@ -176,7 +176,7 @@ public class LoaderCursor extends CursorWrapper {
BitmapInfo iconInfo = li.createIconBitmap(info.iconResource);
li.recycle();
if (iconInfo != null) {
iconInfo.applyTo(info);
info.applyFrom(iconInfo);
return true;
}
}
@@ -185,7 +185,7 @@ public class LoaderCursor extends CursorWrapper {
// Failed to load from resource, try loading from DB.
byte[] data = getBlob(iconIndex);
try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length)).applyTo(info);
info.applyFrom(li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length)));
return true;
} catch (Exception e) {
Log.e(TAG, "Failed to load icon for info " + info, e);

View File

@@ -498,8 +498,8 @@ public class LoaderTask implements Runnable {
c.loadIcon(finalInfo) ? finalInfo.iconBitmap : null;
LauncherIcons li = LauncherIcons.obtain(context);
li.createShortcutIcon(pinnedShortcut,
true /* badged */, fallbackIconProvider).applyTo(info);
info.applyFrom(li.createShortcutIcon(pinnedShortcut,
true /* badged */, fallbackIconProvider));
li.recycle();
if (pmHelper.isAppSuspended(
pinnedShortcut.getPackage(), info.user)) {

View File

@@ -194,7 +194,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
BitmapInfo iconInfo = li.createIconBitmap(si.iconResource);
li.recycle();
if (iconInfo != null) {
iconInfo.applyTo(si);
si.applyFrom(iconInfo);
infoUpdated = true;
}
}

View File

@@ -96,8 +96,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);
li.createShortcutIcon(fullDetails, true, Provider.of(shortcutInfo.iconBitmap))
.applyTo(shortcutInfo);
shortcutInfo.applyFrom(li.createShortcutIcon(fullDetails, true,
Provider.of(shortcutInfo.iconBitmap)));
li.recycle();
updatedShortcutInfos.add(shortcutInfo);
}

View File

@@ -95,7 +95,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);
li.createShortcutIcon(shortcut, true, Provider.of(si.iconBitmap)).applyTo(si);
si.applyFrom(li.createShortcutIcon(shortcut, true, Provider.of(si.iconBitmap)));
li.recycle();
} else {
si.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;

View File

@@ -150,7 +150,7 @@ public class PopupPopulator {
final ShortcutInfo si = new ShortcutInfo(shortcut, launcher);
// Use unbadged icon for the menu.
LauncherIcons li = LauncherIcons.obtain(launcher);
li.createShortcutIcon(shortcut, false /* badged */).applyTo(si);
si.applyFrom(li.createShortcutIcon(shortcut, false /* badged */));
li.recycle();
si.rank = i;