Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84fb31d2 authored by Pinyao Ting's avatar Pinyao Ting
Browse files

Explicit Nullbility in IconCache (Part 1)

This is the first CL in the series to address potential NPE caused by
ambiguous nullabality within Launcher.

Bug: 242895652
Test: manual
Change-Id: I5364d88013c3546c5a5aa03dbe7a75e6fe49a886
parent 4b7c8fce
Loading
Loading
Loading
Loading
+64 −20
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ import androidx.annotation.Nullable;
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.
@@ -51,12 +53,24 @@ public class BaseIconFactory implements AutoCloseable {

    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;
@@ -64,8 +78,12 @@ public class BaseIconFactory implements AutoCloseable {

    protected boolean mMonoIconEnabled;

    @Nullable
    private IconNormalizer mNormalizer;

    @Nullable
    private ShadowGenerator mShadowGenerator;

    private final boolean mShapeDetection;

    // Shadow bitmap used as background for theme icons
@@ -100,6 +118,7 @@ public class BaseIconFactory implements AutoCloseable {
        mDisableColorExtractor = false;
    }

    @NonNull
    public ShadowGenerator getShadowGenerator() {
        if (mShadowGenerator == null) {
            mShadowGenerator = new ShadowGenerator(mIconBitmapSize);
@@ -107,6 +126,7 @@ public class BaseIconFactory implements AutoCloseable {
        return mShadowGenerator;
    }

    @NonNull
    public IconNormalizer getNormalizer() {
        if (mNormalizer == null) {
            mNormalizer = new IconNormalizer(mContext, mIconBitmapSize, mShapeDetection);
@@ -155,6 +175,7 @@ public class BaseIconFactory implements AutoCloseable {
    /**
     * 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();
@@ -164,6 +185,7 @@ public class BaseIconFactory implements AutoCloseable {
        return createBadgedIconBitmap(d, options);
    }

    @NonNull
    public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon) {
        return createBadgedIconBitmap(icon, null);
    }
@@ -176,6 +198,7 @@ public class BaseIconFactory implements AutoCloseable {
     * @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;
@@ -202,6 +225,7 @@ public class BaseIconFactory implements AutoCloseable {
        return info;
    }

    @NonNull
    public FlagOp getBitmapFlagOp(@Nullable IconOptions options) {
        FlagOp op = FlagOp.NO_OP;
        if (options != null) {
@@ -228,6 +252,7 @@ public class BaseIconFactory implements AutoCloseable {
    }

    /** package private */
    @NonNull
    Bitmap getWhiteShadowLayer() {
        if (mWhiteShadowLayer == null) {
            mWhiteShadowLayer = createScaledBitmapWithShadow(
@@ -236,15 +261,16 @@ public class BaseIconFactory implements AutoCloseable {
        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);
        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);
@@ -255,7 +281,7 @@ public class BaseIconFactory implements AutoCloseable {
    /**
     * 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;
    }

@@ -266,8 +292,10 @@ public class BaseIconFactory implements AutoCloseable {
        mDisableColorExtractor = true;
    }

    protected 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;
        }
@@ -298,12 +326,14 @@ public class BaseIconFactory implements AutoCloseable {
        return icon;
    }

    protected Bitmap createIconBitmap(Drawable icon, float scale) {
    @NonNull
    protected Bitmap createIconBitmap(@Nullable final Drawable icon, final float scale) {
        return createIconBitmap(icon, scale, BITMAP_GENERATION_MODE_DEFAULT);
    }

    protected Bitmap createIconBitmap(@NonNull Drawable icon, float scale,
            int bitmapGenerationMode) {
    @NonNull
    protected Bitmap createIconBitmap(@Nullable final Drawable icon, final float scale,
            final int bitmapGenerationMode) {
        final int size = mIconBitmapSize;

        final Bitmap bitmap;
@@ -381,36 +411,42 @@ public class BaseIconFactory implements AutoCloseable {
        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;
        }
@@ -418,7 +454,8 @@ public class BaseIconFactory implements AutoCloseable {
        /**
         * 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;
        }
@@ -426,7 +463,8 @@ public class BaseIconFactory implements AutoCloseable {
        /**
         * If this icon represents an instant app
         */
        public IconOptions setInstantApp(boolean instantApp) {
        @NonNull
        public IconOptions setInstantApp(final boolean instantApp) {
            mIsInstantApp = instantApp;
            return this;
        }
@@ -439,7 +477,7 @@ public class BaseIconFactory implements AutoCloseable {
     */
    private static class FixedSizeBitmapDrawable extends BitmapDrawable {

        public FixedSizeBitmapDrawable(Bitmap bitmap) {
        public FixedSizeBitmapDrawable(@Nullable final Bitmap bitmap) {
            super(null, bitmap);
        }

@@ -468,9 +506,10 @@ public class BaseIconFactory implements AutoCloseable {

    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);
        }
@@ -487,11 +526,16 @@ public class BaseIconFactory implements AutoCloseable {

    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(String text, int color) {
        CenterTextDrawable(@NonNull final String text, final int color) {
            mText = text;
            mTextPaint.setColor(color);
        }
+13 −2
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package com.android.launcher3.icons;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.SparseArray;

import androidx.annotation.NonNull;

import java.util.Arrays;

/**
@@ -26,16 +29,24 @@ import java.util.Arrays;
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 @@ public class ColorExtractor {
     * 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);
+98 −54
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.util.SparseArray;
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 @@ public abstract class BaseIconCache {

        @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 @@ public abstract class BaseIconCache {
     * 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 @@ public abstract class BaseIconCache {
        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 @@ public abstract class BaseIconCache {
        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 @@ public abstract class BaseIconCache {
    /**
     * 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 @@ public abstract class BaseIconCache {
    /**
     * 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 @@ public abstract class BaseIconCache {
                new String[]{packageName + "/%", Long.toString(userSerial)});
    }

    @NonNull
    public IconCacheUpdateHandler getUpdateHandler() {
        updateSystemState();
        return new IconCacheUpdateHandler(this);
@@ -240,7 +270,8 @@ public abstract class BaseIconCache {
        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 @@ public abstract class BaseIconCache {
     *                        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 @@ public abstract class BaseIconCache {

        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 @@ public abstract class BaseIconCache {
     * 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 @@ public abstract class BaseIconCache {
        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 @@ public abstract class BaseIconCache {
        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 abstract class BaseIconCache {
        }
    }

    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 @@ public abstract class BaseIconCache {
     * 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 @@ public abstract class BaseIconCache {
                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,17 +434,16 @@ public abstract class BaseIconCache {
    /**
     * 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;
@@ -416,10 +453,9 @@ public abstract class BaseIconCache {
                    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 @@ public abstract class BaseIconCache {
     * 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 @@ public abstract class BaseIconCache {
     * 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 @@ public abstract class BaseIconCache {
        }
    }

    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 @@ public abstract class BaseIconCache {
     * 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 @@ public abstract class BaseIconCache {
        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 @@ public abstract class BaseIconCache {
    }

    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 @@ public abstract class BaseIconCache {
        }
    }

    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));
+12 −7

File changed.

Preview size limit exceeded, changes collapsed.

+5 −2

File changed.

Preview size limit exceeded, changes collapsed.