Snap for 9239618 from 34bc3c48b081547bcb9409879bb466ef9c4e2690 to tm-platform-release
Change-Id: I864d8c994efb932d51ad56f2cb29467de562569a
diff --git a/iconloaderlib/build.gradle b/iconloaderlib/build.gradle
index 10ec889..23c7cb0 100644
--- a/iconloaderlib/build.gradle
+++ b/iconloaderlib/build.gradle
@@ -1,14 +1,8 @@
-apply plugin: 'com.android.library'
+plugins {
+ id 'sysuigradleproject.android-library-conventions'
+}
android {
- compileSdkVersion COMPILE_SDK
- buildToolsVersion BUILD_TOOLS_VERSION
-
- defaultConfig {
- minSdkVersion 26
- targetSdkVersion 28
- }
-
sourceSets {
main {
java.srcDirs = ['src', 'src_full_lib']
@@ -24,13 +18,8 @@
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
}
dependencies {
- implementation "androidx.core:core:${ANDROID_X_VERSION}"
+ implementation "androidx.core:core"
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
index c0be55d..836d3a8 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -1,5 +1,6 @@
package com.android.launcher3.icons;
+import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static android.graphics.Paint.DITHER_FLAG;
import static android.graphics.Paint.FILTER_BITMAP_FLAG;
import static android.graphics.drawable.AdaptiveIconDrawable.getExtraInsetFraction;
@@ -36,6 +37,8 @@
import com.android.launcher3.icons.BitmapInfo.Extender;
import com.android.launcher3.util.FlagOp;
+import java.util.Objects;
+
/**
* This class will be moved to androidx library. There shouldn't be any dependency outside
* this package.
@@ -44,14 +47,30 @@
private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE;
+ protected static final int BITMAP_GENERATION_MODE_DEFAULT = 0;
+ protected static final int BITMAP_GENERATION_MODE_ALPHA = 1;
+ protected static final int BITMAP_GENERATION_MODE_WITH_SHADOW = 2;
+
private static final float ICON_BADGE_SCALE = 0.444f;
+ @NonNull
private final Rect mOldBounds = new Rect();
+
+ @NonNull
private final SparseBooleanArray mIsUserBadged = new SparseBooleanArray();
+
+ @NonNull
protected final Context mContext;
+
+ @NonNull
private final Canvas mCanvas;
+
+ @NonNull
private final PackageManager mPm;
+
+ @NonNull
private final ColorExtractor mColorExtractor;
+
private boolean mDisableColorExtractor;
protected final int mFillResIconDpi;
@@ -59,8 +78,12 @@
protected boolean mMonoIconEnabled;
+ @Nullable
private IconNormalizer mNormalizer;
+
+ @Nullable
private ShadowGenerator mShadowGenerator;
+
private final boolean mShapeDetection;
// Shadow bitmap used as background for theme icons
@@ -69,8 +92,6 @@
private Drawable mWrapperIcon;
private int mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND;
- private final Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- private static final float PLACEHOLDER_TEXT_SIZE = 20f;
private static int PLACEHOLDER_BACKGROUND_COLOR = Color.rgb(245, 245, 245);
protected BaseIconFactory(Context context, int fillResIconDpi, int iconBitmapSize,
@@ -85,10 +106,6 @@
mCanvas = new Canvas();
mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG));
- mTextPaint.setTextAlign(Paint.Align.CENTER);
- mTextPaint.setColor(PLACEHOLDER_BACKGROUND_COLOR);
- mTextPaint.setTextSize(context.getResources().getDisplayMetrics().density *
- PLACEHOLDER_TEXT_SIZE);
clear();
}
@@ -101,6 +118,7 @@
mDisableColorExtractor = false;
}
+ @NonNull
public ShadowGenerator getShadowGenerator() {
if (mShadowGenerator == null) {
mShadowGenerator = new ShadowGenerator(mIconBitmapSize);
@@ -108,6 +126,7 @@
return mShadowGenerator;
}
+ @NonNull
public IconNormalizer getNormalizer() {
if (mNormalizer == null) {
mNormalizer = new IconNormalizer(mContext, mIconBitmapSize, mShapeDetection);
@@ -138,16 +157,11 @@
* @return
*/
public BitmapInfo createIconBitmap(String placeholder, int color) {
- Bitmap placeholderBitmap = Bitmap.createBitmap(mIconBitmapSize, mIconBitmapSize,
- Bitmap.Config.ARGB_8888);
- mTextPaint.setColor(color);
- Canvas canvas = new Canvas(placeholderBitmap);
- canvas.drawText(placeholder, mIconBitmapSize / 2, mIconBitmapSize * 5 / 8, mTextPaint);
AdaptiveIconDrawable drawable = new AdaptiveIconDrawable(
new ColorDrawable(PLACEHOLDER_BACKGROUND_COLOR),
- new BitmapDrawable(mContext.getResources(), placeholderBitmap));
+ new CenterTextDrawable(placeholder, color));
Bitmap icon = createIconBitmap(drawable, IconNormalizer.ICON_VISIBLE_AREA_FACTOR);
- return BitmapInfo.of(icon, extractColor(icon));
+ return BitmapInfo.of(icon, color);
}
public BitmapInfo createIconBitmap(Bitmap icon) {
@@ -161,6 +175,7 @@
/**
* Creates an icon from the bitmap cropped to the current device icon shape
*/
+ @NonNull
public BitmapInfo createShapedIconBitmap(Bitmap icon, IconOptions options) {
Drawable d = new FixedSizeBitmapDrawable(icon);
float inset = getExtraInsetFraction();
@@ -170,6 +185,7 @@
return createBadgedIconBitmap(d, options);
}
+ @NonNull
public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon) {
return createBadgedIconBitmap(icon, null);
}
@@ -182,17 +198,13 @@
* @return a bitmap suitable for disaplaying as an icon at various system UIs.
*/
@TargetApi(Build.VERSION_CODES.TIRAMISU)
+ @NonNull
public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon,
@Nullable IconOptions options) {
boolean shrinkNonAdaptiveIcons = options == null || options.mShrinkNonAdaptiveIcons;
float[] scale = new float[1];
icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, null, scale);
- Bitmap bitmap = createIconBitmap(icon, scale[0]);
- if (icon instanceof AdaptiveIconDrawable) {
- mCanvas.setBitmap(bitmap);
- getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
- mCanvas.setBitmap(null);
- }
+ Bitmap bitmap = createIconBitmap(icon, scale[0], BITMAP_GENERATION_MODE_WITH_SHADOW);
int color = extractColor(bitmap);
BitmapInfo info = BitmapInfo.of(bitmap, color);
@@ -206,14 +218,14 @@
// Convert mono drawable to bitmap
Drawable paddedMono = new ClippedMonoDrawable(mono);
info.setMonoIcon(
- createIconBitmap(paddedMono, scale[0], mIconBitmapSize, Config.ALPHA_8),
- this);
+ createIconBitmap(paddedMono, scale[0], BITMAP_GENERATION_MODE_ALPHA), this);
}
}
info = info.withFlags(getBitmapFlagOp(options));
return info;
}
+ @NonNull
public FlagOp getBitmapFlagOp(@Nullable IconOptions options) {
FlagOp op = FlagOp.NO_OP;
if (options != null) {
@@ -240,6 +252,7 @@
}
/** package private */
+ @NonNull
Bitmap getWhiteShadowLayer() {
if (mWhiteShadowLayer == null) {
mWhiteShadowLayer = createScaledBitmapWithShadow(
@@ -248,17 +261,16 @@
return mWhiteShadowLayer;
}
- /** package private */
- public Bitmap createScaledBitmapWithShadow(Drawable d) {
+ @NonNull
+ public Bitmap createScaledBitmapWithShadow(@NonNull final Drawable d) {
float scale = getNormalizer().getScale(d, null, null, null);
Bitmap bitmap = createIconBitmap(d, scale);
- mCanvas.setBitmap(bitmap);
- getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
- mCanvas.setBitmap(null);
- return bitmap;
+ return BitmapRenderer.createHardwareBitmap(bitmap.getWidth(), bitmap.getHeight(),
+ canvas -> getShadowGenerator().recreateIcon(bitmap, canvas));
}
- public Bitmap createScaledBitmapWithoutShadow(Drawable icon) {
+ @NonNull
+ public Bitmap createScaledBitmapWithoutShadow(@Nullable Drawable icon) {
RectF iconBounds = new RectF();
float[] scale = new float[1];
icon = normalizeAndWrapToAdaptiveIcon(icon, true, iconBounds, scale);
@@ -269,7 +281,7 @@
/**
* Sets the background color used for wrapped adaptive icon
*/
- public void setWrapperBackgroundColor(int color) {
+ public void setWrapperBackgroundColor(final int color) {
mWrapperBackgroundColor = (Color.alpha(color) < 255) ? DEFAULT_WRAPPER_BACKGROUND : color;
}
@@ -280,8 +292,10 @@
mDisableColorExtractor = true;
}
- private Drawable normalizeAndWrapToAdaptiveIcon(@NonNull Drawable icon,
- boolean shrinkNonAdaptiveIcons, RectF outIconBounds, float[] outScale) {
+ @Nullable
+ protected Drawable normalizeAndWrapToAdaptiveIcon(@Nullable Drawable icon,
+ final boolean shrinkNonAdaptiveIcons, @Nullable final RectF outIconBounds,
+ @NonNull final float[] outScale) {
if (icon == null) {
return null;
}
@@ -312,21 +326,26 @@
return icon;
}
- private Bitmap createIconBitmap(Drawable icon, float scale) {
- return createIconBitmap(icon, scale, mIconBitmapSize);
+ @NonNull
+ protected Bitmap createIconBitmap(@Nullable final Drawable icon, final float scale) {
+ return createIconBitmap(icon, scale, BITMAP_GENERATION_MODE_DEFAULT);
}
- /**
- * @param icon drawable that should be flattened to a bitmap
- * @param scale the scale to apply before drawing {@param icon} on the canvas
- */
- public Bitmap createIconBitmap(@NonNull Drawable icon, float scale, int size) {
- return createIconBitmap(icon, scale, size, Bitmap.Config.ARGB_8888);
- }
+ @NonNull
+ protected Bitmap createIconBitmap(@Nullable final Drawable icon, final float scale,
+ final int bitmapGenerationMode) {
+ final int size = mIconBitmapSize;
- private Bitmap createIconBitmap(@NonNull Drawable icon, float scale, int size,
- Bitmap.Config config) {
- Bitmap bitmap = Bitmap.createBitmap(size, size, config);
+ final Bitmap bitmap;
+ switch (bitmapGenerationMode) {
+ case BITMAP_GENERATION_MODE_ALPHA:
+ bitmap = Bitmap.createBitmap(size, size, Config.ALPHA_8);
+ break;
+ case BITMAP_GENERATION_MODE_WITH_SHADOW:
+ default:
+ bitmap = Bitmap.createBitmap(size, size, Config.ARGB_8888);
+ break;
+ }
if (icon == null) {
return bitmap;
}
@@ -335,11 +354,15 @@
if (icon instanceof AdaptiveIconDrawable) {
int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size),
- Math.round(size * (1 - scale) / 2 ));
+ Math.round(size * (1 - scale) / 2));
// b/211896569: AdaptiveIconDrawable do not work properly for non top-left bounds
icon.setBounds(0, 0, size - offset - offset, size - offset - offset);
int count = mCanvas.save();
mCanvas.translate(offset, offset);
+ if (bitmapGenerationMode == BITMAP_GENERATION_MODE_WITH_SHADOW) {
+ getShadowGenerator().addPathShadow(
+ ((AdaptiveIconDrawable) icon).getIconMask(), mCanvas);
+ }
if (icon instanceof BitmapInfo.Extender) {
((Extender) icon).drawForPersistence(mCanvas);
@@ -351,7 +374,7 @@
if (icon instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
Bitmap b = bitmapDrawable.getBitmap();
- if (bitmap != null && b.getDensity() == Bitmap.DENSITY_NONE) {
+ if (b != null && b.getDensity() == Bitmap.DENSITY_NONE) {
bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
}
}
@@ -388,36 +411,42 @@
clear();
}
+ @NonNull
public BitmapInfo makeDefaultIcon() {
return createBadgedIconBitmap(getFullResDefaultActivityIcon(mFillResIconDpi));
}
- public static Drawable getFullResDefaultActivityIcon(int iconDpi) {
- return Resources.getSystem().getDrawableForDensity(
- android.R.drawable.sym_def_app_icon, iconDpi);
+ @NonNull
+ public static Drawable getFullResDefaultActivityIcon(final int iconDpi) {
+ return Objects.requireNonNull(Resources.getSystem().getDrawableForDensity(
+ android.R.drawable.sym_def_app_icon, iconDpi));
}
- private int extractColor(Bitmap bitmap) {
+ private int extractColor(@NonNull final Bitmap bitmap) {
return mDisableColorExtractor ? 0 : mColorExtractor.findDominantColorByHue(bitmap);
}
/**
* Returns the correct badge size given an icon size
*/
- public static int getBadgeSizeForIconSize(int iconSize) {
+ public static int getBadgeSizeForIconSize(final int iconSize) {
return (int) (ICON_BADGE_SCALE * iconSize);
}
public static class IconOptions {
boolean mShrinkNonAdaptiveIcons = true;
+
boolean mIsInstantApp;
+
+ @Nullable
UserHandle mUserHandle;
/**
* Set to false if non-adaptive icons should not be treated
*/
- public IconOptions setShrinkNonAdaptiveIcons(boolean shrink) {
+ @NonNull
+ public IconOptions setShrinkNonAdaptiveIcons(final boolean shrink) {
mShrinkNonAdaptiveIcons = shrink;
return this;
}
@@ -425,7 +454,8 @@
/**
* User for this icon, in case of badging
*/
- public IconOptions setUser(UserHandle user) {
+ @NonNull
+ public IconOptions setUser(@Nullable final UserHandle user) {
mUserHandle = user;
return this;
}
@@ -433,7 +463,8 @@
/**
* If this icon represents an instant app
*/
- public IconOptions setInstantApp(boolean instantApp) {
+ @NonNull
+ public IconOptions setInstantApp(final boolean instantApp) {
mIsInstantApp = instantApp;
return this;
}
@@ -446,7 +477,7 @@
*/
private static class FixedSizeBitmapDrawable extends BitmapDrawable {
- public FixedSizeBitmapDrawable(Bitmap bitmap) {
+ public FixedSizeBitmapDrawable(@Nullable final Bitmap bitmap) {
super(null, bitmap);
}
@@ -475,9 +506,10 @@
private static class ClippedMonoDrawable extends InsetDrawable {
+ @NonNull
private final AdaptiveIconDrawable mCrop;
- public ClippedMonoDrawable(Drawable base) {
+ public ClippedMonoDrawable(@Nullable final Drawable base) {
super(base, -getExtraInsetFraction());
mCrop = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
}
@@ -491,4 +523,32 @@
canvas.restoreToCount(saveCount);
}
}
+
+ private static class CenterTextDrawable extends ColorDrawable {
+
+ @NonNull
+ private final Rect mTextBounds = new Rect();
+
+ @NonNull
+ private final Paint mTextPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);
+
+ @NonNull
+ private final String mText;
+
+ CenterTextDrawable(@NonNull final String text, final int color) {
+ mText = text;
+ mTextPaint.setColor(color);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ Rect bounds = getBounds();
+ mTextPaint.setTextSize(bounds.height() / 3f);
+ mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
+ canvas.drawText(mText,
+ bounds.exactCenterX() - mTextBounds.exactCenterX(),
+ bounds.exactCenterY() - mTextBounds.exactCenterY(),
+ mTextPaint);
+ }
+ }
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java b/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
index d624805..167fca4 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
@@ -387,7 +387,8 @@
mBgPaint.setColorFilter(cs.mBgFilter);
mThemedFgColor = cs.mThemedFgColor;
- mFullDrawable = (AdaptiveIconDrawable) mAnimInfo.baseDrawableState.newDrawable();
+ mFullDrawable =
+ (AdaptiveIconDrawable) mAnimInfo.baseDrawableState.newDrawable().mutate();
mFG = (LayerDrawable) mFullDrawable.getForeground();
// Time needs to be applied here since drawInternal is NOT guaranteed to be called
@@ -397,6 +398,13 @@
}
@Override
+ public void setAlpha(int alpha) {
+ super.setAlpha(alpha);
+ mBgPaint.setAlpha(alpha);
+ mFG.setAlpha(alpha);
+ }
+
+ @Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
@@ -434,8 +442,7 @@
protected void updateFilter() {
super.updateFilter();
int alpha = mIsDisabled ? (int) (mDisabledAlpha * FULLY_OPAQUE) : FULLY_OPAQUE;
- mBgPaint.setAlpha(alpha);
- mFG.setAlpha(alpha);
+ setAlpha(alpha);
mBgPaint.setColorFilter(mIsDisabled ? getDisabledColorFilter() : mBgFilter);
mFG.setColorFilter(mIsDisabled ? getDisabledColorFilter() : null);
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/ColorExtractor.java b/iconloaderlib/src/com/android/launcher3/icons/ColorExtractor.java
index 87bda82..56bb3ea 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/ColorExtractor.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/ColorExtractor.java
@@ -18,6 +18,9 @@
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.SparseArray;
+
+import androidx.annotation.NonNull;
+
import java.util.Arrays;
/**
@@ -26,16 +29,24 @@
public class ColorExtractor {
private final int NUM_SAMPLES = 20;
+
+ @NonNull
private final float[] mTmpHsv = new float[3];
+
+ @NonNull
private final float[] mTmpHueScoreHistogram = new float[360];
+
+ @NonNull
private final int[] mTmpPixels = new int[NUM_SAMPLES];
+
+ @NonNull
private final SparseArray<Float> mTmpRgbScores = new SparseArray<>();
/**
* This picks a dominant color, looking for high-saturation, high-value, repeated hues.
* @param bitmap The bitmap to scan
*/
- public int findDominantColorByHue(Bitmap bitmap) {
+ public int findDominantColorByHue(@NonNull final Bitmap bitmap) {
return findDominantColorByHue(bitmap, NUM_SAMPLES);
}
@@ -43,7 +54,7 @@
* This picks a dominant color, looking for high-saturation, high-value, repeated hues.
* @param bitmap The bitmap to scan
*/
- public int findDominantColorByHue(Bitmap bitmap, int samples) {
+ public int findDominantColorByHue(@NonNull final Bitmap bitmap, final int samples) {
final int height = bitmap.getHeight();
final int width = bitmap.getWidth();
int sampleStride = (int) Math.sqrt((height * width) / samples);
diff --git a/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java b/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
index 96dee3b..be49ffd 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
@@ -24,6 +24,7 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
@@ -58,22 +59,17 @@
}
public synchronized void recreateIcon(Bitmap icon, Canvas out) {
- recreateIcon(icon, mDefaultBlurMaskFilter, AMBIENT_SHADOW_ALPHA, KEY_SHADOW_ALPHA, out);
- }
-
- public synchronized void recreateIcon(Bitmap icon, BlurMaskFilter blurMaskFilter,
- int ambientAlpha, int keyAlpha, Canvas out) {
if (ENABLE_SHADOWS) {
int[] offset = new int[2];
- mBlurPaint.setMaskFilter(blurMaskFilter);
+ mBlurPaint.setMaskFilter(mDefaultBlurMaskFilter);
Bitmap shadow = icon.extractAlpha(mBlurPaint, offset);
// Draw ambient shadow
- mDrawPaint.setAlpha(ambientAlpha);
+ mDrawPaint.setAlpha(AMBIENT_SHADOW_ALPHA);
out.drawBitmap(shadow, offset[0], offset[1], mDrawPaint);
// Draw key shadow
- mDrawPaint.setAlpha(keyAlpha);
+ mDrawPaint.setAlpha(KEY_SHADOW_ALPHA);
out.drawBitmap(shadow, offset[0], offset[1] + KEY_SHADOW_DISTANCE * mIconSize,
mDrawPaint);
}
@@ -83,6 +79,26 @@
out.drawBitmap(icon, 0, 0, mDrawPaint);
}
+ /** package private **/
+ void addPathShadow(Path path, Canvas out) {
+ if (ENABLE_SHADOWS) {
+ mDrawPaint.setMaskFilter(mDefaultBlurMaskFilter);
+
+ // Draw ambient shadow
+ mDrawPaint.setAlpha(AMBIENT_SHADOW_ALPHA);
+ out.drawPath(path, mDrawPaint);
+
+ // Draw key shadow
+ int save = out.save();
+ mDrawPaint.setAlpha(KEY_SHADOW_ALPHA);
+ out.translate(0, KEY_SHADOW_DISTANCE * mIconSize);
+ out.drawPath(path, mDrawPaint);
+ out.restoreToCount(save);
+
+ mDrawPaint.setMaskFilter(null);
+ }
+ }
+
/**
* Returns the minimum amount by which an icon with {@param bounds} should be scaled
* so that the shadows do not get clipped.
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
index 057bdc2..963e807 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
@@ -54,6 +54,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.BaseIconFactory.IconOptions;
@@ -86,29 +87,50 @@
@NonNull
public BitmapInfo bitmap = BitmapInfo.LOW_RES_INFO;
+ @NonNull
public CharSequence title = "";
+ @NonNull
public CharSequence contentDescription = "";
}
+ @NonNull
protected final Context mContext;
+
+ @NonNull
protected final PackageManager mPackageManager;
+ @NonNull
private final Map<ComponentKey, CacheEntry> mCache;
+
+ @NonNull
protected final Handler mWorkerHandler;
protected int mIconDpi;
+
+ @NonNull
protected IconDB mIconDb;
+
+ @NonNull
protected LocaleList mLocaleList = LocaleList.getEmptyLocaleList();
+
+ @NonNull
protected String mSystemState = "";
+ @Nullable
private BitmapInfo mDefaultIcon;
+
+ @NonNull
private final SparseArray<FlagOp> mUserFlagOpMap = new SparseArray<>();
+ @Nullable
private final String mDbFileName;
+
+ @NonNull
private final Looper mBgLooper;
- public BaseIconCache(Context context, String dbFileName, Looper bgLooper,
- int iconDpi, int iconPixelSize, boolean inMemoryCache) {
+ public BaseIconCache(@NonNull final Context context, @Nullable final String dbFileName,
+ @NonNull final Looper bgLooper, final int iconDpi, final int iconPixelSize,
+ final boolean inMemoryCache) {
mContext = context;
mDbFileName = dbFileName;
mPackageManager = context.getPackageManager();
@@ -141,23 +163,24 @@
* Returns the persistable serial number for {@param user}. Subclass should implement proper
* caching strategy to avoid making binder call every time.
*/
- protected abstract long getSerialNumberForUser(UserHandle user);
+ protected abstract long getSerialNumberForUser(@NonNull final UserHandle user);
/**
* Return true if the given app is an instant app and should be badged appropriately.
*/
- protected abstract boolean isInstantApp(ApplicationInfo info);
+ protected abstract boolean isInstantApp(@NonNull final ApplicationInfo info);
/**
* Opens and returns an icon factory. The factory is recycled by the caller.
*/
+ @NonNull
public abstract BaseIconFactory getIconFactory();
- public void updateIconParams(int iconDpi, int iconPixelSize) {
+ public void updateIconParams(final int iconDpi, final int iconPixelSize) {
mWorkerHandler.post(() -> updateIconParamsBg(iconDpi, iconPixelSize));
}
- private synchronized void updateIconParamsBg(int iconDpi, int iconPixelSize) {
+ private synchronized void updateIconParamsBg(final int iconDpi, final int iconPixelSize) {
mIconDpi = iconDpi;
mDefaultIcon = null;
mUserFlagOpMap.clear();
@@ -167,7 +190,8 @@
mCache.clear();
}
- private Drawable getFullResIcon(Resources resources, int iconId) {
+ @Nullable
+ private Drawable getFullResIcon(@Nullable final Resources resources, final int iconId) {
if (resources != null && iconId != 0) {
try {
return resources.getDrawableForDensity(iconId, mIconDpi);
@@ -176,14 +200,16 @@
return getFullResDefaultActivityIcon(mIconDpi);
}
- public Drawable getFullResIcon(String packageName, int iconId) {
+ @Nullable
+ public Drawable getFullResIcon(@NonNull final String packageName, final int iconId) {
try {
return getFullResIcon(mPackageManager.getResourcesForApplication(packageName), iconId);
} catch (PackageManager.NameNotFoundException e) { }
return getFullResDefaultActivityIcon(mIconDpi);
}
- public Drawable getFullResIcon(ActivityInfo info) {
+ @Nullable
+ public Drawable getFullResIcon(@NonNull final ActivityInfo info) {
try {
return getFullResIcon(mPackageManager.getResourcesForApplication(info.applicationInfo),
info.getIconResource());
@@ -194,14 +220,16 @@
/**
* Remove any records for the supplied ComponentName.
*/
- public synchronized void remove(ComponentName componentName, UserHandle user) {
+ public synchronized void remove(@NonNull final ComponentName componentName,
+ @NonNull final UserHandle user) {
mCache.remove(new ComponentKey(componentName, user));
}
/**
* Remove any records for the supplied package name from memory.
*/
- private void removeFromMemCacheLocked(String packageName, UserHandle user) {
+ private void removeFromMemCacheLocked(@Nullable final String packageName,
+ @Nullable final UserHandle user) {
HashSet<ComponentKey> forDeletion = new HashSet<>();
for (ComponentKey key: mCache.keySet()) {
if (key.componentName.getPackageName().equals(packageName)
@@ -217,7 +245,8 @@
/**
* Removes the entries related to the given package in memory and persistent DB.
*/
- public synchronized void removeIconsForPkg(String packageName, UserHandle user) {
+ public synchronized void removeIconsForPkg(@NonNull final String packageName,
+ @NonNull final UserHandle user) {
removeFromMemCacheLocked(packageName, user);
long userSerial = getSerialNumberForUser(user);
mIconDb.delete(
@@ -225,6 +254,7 @@
new String[]{packageName + "/%", Long.toString(userSerial)});
}
+ @NonNull
public IconCacheUpdateHandler getUpdateHandler() {
updateSystemState();
return new IconCacheUpdateHandler(this);
@@ -240,7 +270,8 @@
mSystemState = mLocaleList.toLanguageTags() + "," + Build.VERSION.SDK_INT;
}
- protected String getIconSystemState(String packageName) {
+ @NonNull
+ protected String getIconSystemState(@Nullable final String packageName) {
return mSystemState;
}
@@ -251,8 +282,9 @@
* old data.
*/
@VisibleForTesting
- public synchronized <T> void addIconToDBAndMemCache(T object, CachingLogic<T> cachingLogic,
- PackageInfo info, long userSerial, boolean replaceExisting) {
+ public synchronized <T> void addIconToDBAndMemCache(@NonNull final T object,
+ @NonNull final CachingLogic<T> cachingLogic, @NonNull final PackageInfo info,
+ final long userSerial, final boolean replaceExisting) {
UserHandle user = cachingLogic.getUser(object);
ComponentName componentName = cachingLogic.getComponent(object);
@@ -276,7 +308,8 @@
CharSequence entryTitle = cachingLogic.getLabel(object);
if (entryTitle == null) {
- Log.d(TAG, "No label returned from caching logic instance: " + cachingLogic);
+ Log.wtf(TAG, "No label returned from caching logic instance: " + cachingLogic);
+ entryTitle = "";
}
entry.title = entryTitle;
@@ -293,8 +326,8 @@
* Updates {@param values} to contain versioning information and adds it to the DB.
* @param values {@link ContentValues} containing icon & title
*/
- private void addIconToDB(ContentValues values, ComponentName key,
- PackageInfo info, long userSerial, long lastUpdateTime) {
+ private void addIconToDB(@NonNull final ContentValues values, @NonNull final ComponentName key,
+ @NonNull final PackageInfo info, final long userSerial, final long lastUpdateTime) {
values.put(IconDB.COLUMN_COMPONENT, key.flattenToString());
values.put(IconDB.COLUMN_USER, userSerial);
values.put(IconDB.COLUMN_LAST_UPDATED, lastUpdateTime);
@@ -302,7 +335,8 @@
mIconDb.insertOrReplace(values);
}
- public synchronized BitmapInfo getDefaultIcon(UserHandle user) {
+ @NonNull
+ public synchronized BitmapInfo getDefaultIcon(@NonNull final UserHandle user) {
if (mDefaultIcon == null) {
try (BaseIconFactory li = getIconFactory()) {
mDefaultIcon = li.makeDefaultIcon();
@@ -311,7 +345,8 @@
return mDefaultIcon.withFlags(getUserFlagOpLocked(user));
}
- protected FlagOp getUserFlagOpLocked(UserHandle user) {
+ @NonNull
+ protected FlagOp getUserFlagOpLocked(@NonNull final UserHandle user) {
int key = user.hashCode();
int index;
if ((index = mUserFlagOpMap.indexOfKey(key)) >= 0) {
@@ -325,7 +360,7 @@
}
}
- public boolean isDefaultIcon(BitmapInfo icon, UserHandle user) {
+ public boolean isDefaultIcon(@NonNull final BitmapInfo icon, @NonNull final UserHandle user) {
return getDefaultIcon(user).icon == icon.icon;
}
@@ -333,10 +368,11 @@
* Retrieves the entry from the cache. If the entry is not present, it creates a new entry.
* This method is not thread safe, it must be called from a synchronized method.
*/
+ @NonNull
protected <T> CacheEntry cacheLocked(
- @NonNull ComponentName componentName, @NonNull UserHandle user,
- @NonNull Supplier<T> infoProvider, @NonNull CachingLogic<T> cachingLogic,
- boolean usePackageIcon, boolean useLowResIcon) {
+ @NonNull final ComponentName componentName, @NonNull final UserHandle user,
+ @NonNull final Supplier<T> infoProvider, @NonNull final CachingLogic<T> cachingLogic,
+ final boolean usePackageIcon, final boolean useLowResIcon) {
return cacheLocked(
componentName,
user,
@@ -347,10 +383,12 @@
useLowResIcon);
}
+ @NonNull
protected <T> CacheEntry cacheLocked(
- @NonNull ComponentName componentName, @NonNull UserHandle user,
- @NonNull Supplier<T> infoProvider, @NonNull CachingLogic<T> cachingLogic,
- @Nullable Cursor cursor, boolean usePackageIcon, boolean useLowResIcon) {
+ @NonNull final ComponentName componentName, @NonNull final UserHandle user,
+ @NonNull final Supplier<T> infoProvider, @NonNull final CachingLogic<T> cachingLogic,
+ @Nullable final Cursor cursor, final boolean usePackageIcon,
+ final boolean useLowResIcon) {
assertWorkerThread();
ComponentKey cacheKey = new ComponentKey(componentName, user);
CacheEntry entry = mCache.get(cacheKey);
@@ -396,30 +434,28 @@
/**
* Fallback method for loading an icon bitmap.
*/
- protected <T> void loadFallbackIcon(
- T object, CacheEntry entry, @NonNull CachingLogic<T> cachingLogic,
- boolean usePackageIcon, boolean usePackageTitle, @NonNull ComponentName componentName,
- @NonNull UserHandle user) {
+ protected <T> void loadFallbackIcon(@Nullable final T object, @NonNull final CacheEntry entry,
+ @NonNull final CachingLogic<T> cachingLogic, final boolean usePackageIcon,
+ final boolean usePackageTitle, @NonNull final ComponentName componentName,
+ @NonNull final UserHandle user) {
if (object != null) {
entry.bitmap = cachingLogic.loadIcon(mContext, object);
} else {
if (usePackageIcon) {
CacheEntry packageEntry = getEntryForPackageLocked(
componentName.getPackageName(), user, false);
- if (packageEntry != null) {
- if (DEBUG) Log.d(TAG, "using package default icon for " +
- componentName.toShortString());
- entry.bitmap = packageEntry.bitmap;
- entry.contentDescription = packageEntry.contentDescription;
+ if (DEBUG) Log.d(TAG, "using package default icon for " +
+ componentName.toShortString());
+ entry.bitmap = packageEntry.bitmap;
+ entry.contentDescription = packageEntry.contentDescription;
- if (usePackageTitle) {
- entry.title = packageEntry.title;
- }
+ if (usePackageTitle) {
+ entry.title = packageEntry.title;
}
}
if (entry.bitmap == null) {
- if (DEBUG) Log.d(TAG, "using default icon for " +
- componentName.toShortString());
+ // TODO: entry.bitmap can never be null, so this should not happen at all.
+ Log.wtf(TAG, "using default icon for " + componentName.toShortString());
entry.bitmap = getDefaultIcon(user);
}
}
@@ -429,8 +465,8 @@
* Fallback method for loading an app title.
*/
protected <T> void loadFallbackTitle(
- T object, CacheEntry entry, @NonNull CachingLogic<T> cachingLogic,
- @NonNull UserHandle user) {
+ @NonNull final T object, @NonNull final CacheEntry entry,
+ @NonNull final CachingLogic<T> cachingLogic, @NonNull final UserHandle user) {
entry.title = cachingLogic.getLabel(object);
entry.contentDescription = mPackageManager.getUserBadgedLabel(
cachingLogic.getDescription(object, entry.title), user);
@@ -445,8 +481,9 @@
* Adds a default package entry in the cache. This entry is not persisted and will be removed
* when the cache is flushed.
*/
- protected synchronized void cachePackageInstallInfo(String packageName, UserHandle user,
- Bitmap icon, CharSequence title) {
+ protected synchronized void cachePackageInstallInfo(@NonNull final String packageName,
+ @NonNull final UserHandle user, @Nullable final Bitmap icon,
+ @Nullable final CharSequence title) {
removeFromMemCacheLocked(packageName, user);
ComponentKey cacheKey = getPackageKey(packageName, user);
@@ -469,7 +506,9 @@
}
}
- private static ComponentKey getPackageKey(String packageName, UserHandle user) {
+ @NonNull
+ private static ComponentKey getPackageKey(@NonNull final String packageName,
+ @NonNull final UserHandle user) {
ComponentName cn = new ComponentName(packageName, packageName + EMPTY_CLASS_NAME);
return new ComponentKey(cn, user);
}
@@ -478,8 +517,10 @@
* Gets an entry for the package, which can be used as a fallback entry for various components.
* This method is not thread safe, it must be called from a synchronized method.
*/
- protected CacheEntry getEntryForPackageLocked(String packageName, UserHandle user,
- boolean useLowResIcon) {
+ @WorkerThread
+ @NonNull
+ protected CacheEntry getEntryForPackageLocked(@NonNull final String packageName,
+ @NonNull final UserHandle user, final boolean useLowResIcon) {
assertWorkerThread();
ComponentKey cacheKey = getPackageKey(packageName, user);
CacheEntry entry = mCache.get(cacheKey);
@@ -533,8 +574,8 @@
return entry;
}
- protected boolean getEntryFromDBLocked(
- ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
+ protected boolean getEntryFromDBLocked(@NonNull final ComponentKey cacheKey,
+ @NonNull final CacheEntry entry, final boolean lowRes) {
Cursor c = null;
Trace.beginSection("loadIconIndividually");
try {
@@ -559,7 +600,8 @@
}
private boolean updateTitleAndIconLocked(
- ComponentKey cacheKey, CacheEntry entry, Cursor c, boolean lowRes) {
+ @NonNull final ComponentKey cacheKey, @NonNull final CacheEntry entry,
+ @NonNull final Cursor c, final boolean lowRes) {
// Set the alpha to be 255, so that we never have a wrong color
entry.bitmap = BitmapInfo.of(LOW_RES_ICON,
setColorAlphaBound(c.getInt(IconDB.INDEX_COLOR), 255));
@@ -678,8 +720,10 @@
}
}
- private ContentValues newContentValues(BitmapInfo bitmapInfo, String label,
- String packageName, @Nullable String keywords) {
+ @NonNull
+ private ContentValues newContentValues(@NonNull final BitmapInfo bitmapInfo,
+ @NonNull final String label, @NonNull final String packageName,
+ @Nullable final String keywords) {
ContentValues values = new ContentValues();
if (bitmapInfo.canPersist()) {
values.put(IconDB.COLUMN_ICON, flattenBitmap(bitmapInfo.icon));
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
index c12e9dc..8034d6e 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
@@ -28,31 +28,36 @@
public interface CachingLogic<T> {
- ComponentName getComponent(T object);
+ @NonNull
+ ComponentName getComponent(@NonNull final T object);
- UserHandle getUser(T object);
+ @NonNull
+ UserHandle getUser(@NonNull final T object);
- CharSequence getLabel(T object);
+ @NonNull
+ CharSequence getLabel(@NonNull final T object);
- default CharSequence getDescription(T object, CharSequence fallback) {
+ @NonNull
+ default CharSequence getDescription(@NonNull final T object,
+ @NonNull final CharSequence fallback) {
return fallback;
}
@NonNull
- BitmapInfo loadIcon(Context context, T object);
+ BitmapInfo loadIcon(@NonNull final Context context, @NonNull final T object);
/**
* Provides a option list of keywords to associate with this object
*/
@Nullable
- default String getKeywords(T object, LocaleList localeList) {
+ default String getKeywords(@NonNull final T object, @NonNull final LocaleList localeList) {
return null;
}
/**
* Returns the timestamp the entry was last updated in cache.
*/
- default long getLastUpdatedTime(T object, PackageInfo info) {
+ default long getLastUpdatedTime(@Nullable final T object, @NonNull final PackageInfo info) {
return info.lastUpdateTime;
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
index 9e1ad7b..aec1cdd 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
@@ -180,7 +180,8 @@
long updateTime = c.getLong(indexLastUpdate);
int version = c.getInt(indexVersion);
T app = componentMap.remove(component);
- if (version == info.versionCode && updateTime == info.lastUpdateTime
+ if (version == info.versionCode
+ && updateTime == cachingLogic.getLastUpdatedTime(app, info)
&& TextUtils.equals(c.getString(systemStateIndex),
mIconCache.getIconSystemState(info.packageName))) {
diff --git a/iconloaderlib/src_full_lib/com/android/launcher3/icons/SimpleIconCache.java b/iconloaderlib/src_full_lib/com/android/launcher3/icons/SimpleIconCache.java
index cc4ad7b..63ba887 100644
--- a/iconloaderlib/src_full_lib/com/android/launcher3/icons/SimpleIconCache.java
+++ b/iconloaderlib/src_full_lib/com/android/launcher3/icons/SimpleIconCache.java
@@ -32,6 +32,8 @@
import android.os.UserManager;
import android.util.SparseLongArray;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.icons.cache.BaseIconCache;
/**
@@ -64,7 +66,7 @@
}
@Override
- protected long getSerialNumberForUser(UserHandle user) {
+ protected long getSerialNumberForUser(@NonNull UserHandle user) {
synchronized (mUserSerialMap) {
int index = mUserSerialMap.indexOfKey(user.getIdentifier());
if (index >= 0) {
@@ -83,10 +85,11 @@
}
@Override
- protected boolean isInstantApp(ApplicationInfo info) {
+ protected boolean isInstantApp(@NonNull ApplicationInfo info) {
return info.isInstantApp();
}
+ @NonNull
@Override
public BaseIconFactory getIconFactory() {
return IconFactory.obtain(mContext);
diff --git a/searchuilib/build.gradle b/searchuilib/build.gradle
index 3bf65fe..6b5027b 100644
--- a/searchuilib/build.gradle
+++ b/searchuilib/build.gradle
@@ -1,12 +1,14 @@
-apply plugin: 'com.android.library'
+plugins {
+ id 'com.android.library'
+}
android {
- compileSdkVersion COMPILE_SDK
- buildToolsVersion BUILD_TOOLS_VERSION
+ compileSdk TARGET_SDK.toInteger()
+ buildToolsVersion = BUILD_TOOLS_VERSION
defaultConfig {
- minSdkVersion 25
- targetSdkVersion 28
+ minSdkVersion TARGET_SDK.toInteger()
+ targetSdkVersion TARGET_SDK.toInteger()
}
sourceSets {
@@ -31,5 +33,5 @@
}
dependencies {
- implementation "androidx.core:core:${ANDROID_X_VERSION}"
+ implementation "androidx.core:core:+"
}
diff --git a/searchuilib/src/com/android/app/search/LayoutType.java b/searchuilib/src/com/android/app/search/LayoutType.java
index d7c28ab..072c09b 100644
--- a/searchuilib/src/com/android/app/search/LayoutType.java
+++ b/searchuilib/src/com/android/app/search/LayoutType.java
@@ -47,6 +47,9 @@
public static final String SMALL_ICON_HORIZONTAL_TEXT = "short_icon_row";
public static final String SMALL_ICON_HORIZONTAL_TEXT_THUMBNAIL = "short_icon_row_thumbnail";
+ // This layout contains a series of thumbnails (currently up to 3 per row)
+ public static final String THUMBNAIL_CONTAINER = "thumbnail_container";
+
// This layout creates square thumbnail image (currently 3 column)
public static final String THUMBNAIL = "thumbnail";