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

Commit b2136311 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Adding some source hints when generating theme icons

Bug: 381897614
Flag: EXEMPT refactor
Test: Presubmit
Change-Id: Ibdf7b6cf218884be8577a09b8e129fab42f3bc92
parent c40e2aa0
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -242,7 +242,8 @@ public class BaseIconFactory implements AutoCloseable {
        if (adaptiveIcon instanceof Extender extender) {
            info = extender.getExtendedInfo(bitmap, color, this, scale[0]);
        } else if (IconProvider.ATLEAST_T && mThemeController != null && adaptiveIcon != null) {
            info.setThemedBitmap(mThemeController.createThemedBitmap(adaptiveIcon, info, this));
            info.setThemedBitmap(mThemeController.createThemedBitmap(
                    adaptiveIcon, info, this, options == null ? null : options.mSourceHint));
        }
        info = info.withFlags(getBitmapFlagOp(options));
        return info;
@@ -526,6 +527,8 @@ public class BaseIconFactory implements AutoCloseable {
        @Nullable
        Integer mExtractedColor;

        @Nullable
        SourceHint mSourceHint;

        /**
         * User for this icon, in case of badging
@@ -580,6 +583,15 @@ public class BaseIconFactory implements AutoCloseable {
            mGenerationMode = generationMode;
            return this;
        }

        /**
         * User for this icon, in case of badging
         */
        @NonNull
        public IconOptions setSourceHint(@Nullable SourceHint sourceHint) {
            mSourceHint = sourceHint;
            return this;
        }
    }

    /**
+15 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.launcher3.icons

import android.content.Context
import android.graphics.drawable.AdaptiveIconDrawable
import com.android.launcher3.icons.cache.CachingLogic
import com.android.launcher3.util.ComponentKey

/** Represents a themed version of a BitmapInfo */
interface ThemedBitmap {
@@ -34,9 +36,15 @@ interface IconThemeController {
        icon: AdaptiveIconDrawable,
        info: BitmapInfo,
        factory: BaseIconFactory,
        sourceHint: SourceHint? = null,
    ): ThemedBitmap?

    fun decode(data: ByteArray, info: BitmapInfo, factory: BaseIconFactory): ThemedBitmap?
    fun decode(
        data: ByteArray,
        info: BitmapInfo,
        factory: BaseIconFactory,
        sourceHint: SourceHint,
    ): ThemedBitmap?

    fun createThemedAdaptiveIcon(
        context: Context,
@@ -44,3 +52,9 @@ interface IconThemeController {
        info: BitmapInfo?,
    ): AdaptiveIconDrawable?
}

data class SourceHint(
    val key: ComponentKey,
    val logic: CachingLogic<*>,
    val freshnessId: String? = null,
)
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.launcher3.icons.cache

import android.content.ComponentName
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.os.UserHandle
import com.android.launcher3.icons.BaseIconFactory.IconOptions
import com.android.launcher3.icons.BitmapInfo
import com.android.launcher3.icons.IconProvider
import com.android.launcher3.icons.cache.BaseIconCache.Companion.EMPTY_CLASS_NAME

/** Caching logic for ApplicationInfo */
class AppInfoCachingLogic(
    private val pm: PackageManager,
    private val instantAppResolver: (ApplicationInfo) -> Boolean,
    private val errorLogger: (String, Exception?) -> Unit = { _, _ -> },
) : CachingLogic<ApplicationInfo> {

    override fun getComponent(info: ApplicationInfo) =
        ComponentName(info.packageName, info.packageName + EMPTY_CLASS_NAME)

    override fun getUser(info: ApplicationInfo) = UserHandle.getUserHandleForUid(info.uid)

    override fun getLabel(info: ApplicationInfo) = info.loadLabel(pm)

    override fun getApplicationInfo(info: ApplicationInfo) = info

    override fun loadIcon(
        context: Context,
        cache: BaseIconCache,
        info: ApplicationInfo,
    ): BitmapInfo {
        // Load the full res icon for the application, but if useLowResIcon is set, then
        // only keep the low resolution icon instead of the larger full-sized icon
        val appIcon = cache.iconProvider.getIcon(info)
        if (context.packageManager.isDefaultApplicationIcon(appIcon)) {
            errorLogger.invoke(
                String.format("Default icon returned for %s", info.packageName),
                null,
            )
        }

        return cache.iconFactory.use { li ->
            li.createBadgedIconBitmap(
                appIcon,
                IconOptions()
                    .setUser(getUser(info))
                    .setInstantApp(instantAppResolver.invoke(info))
                    .setSourceHint(getSourceHint(info, cache)),
            )
        }
    }

    override fun getFreshnessIdentifier(item: ApplicationInfo, iconProvider: IconProvider) =
        iconProvider.getStateForApp(item)
}
+25 −25
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import com.android.launcher3.icons.BaseIconFactory.IconOptions
import com.android.launcher3.icons.BitmapInfo
import com.android.launcher3.icons.GraphicsUtils
import com.android.launcher3.icons.IconProvider
import com.android.launcher3.icons.SourceHint
import com.android.launcher3.icons.cache.CacheLookupFlag.Companion.DEFAULT_LOOKUP_FLAG
import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.FlagOp
@@ -95,6 +96,13 @@ constructor(
    private val userFlagOpMap = SparseArray<FlagOp>()
    private val userFormatString = SparseArray<String?>()

    private val appInfoCachingLogic =
        AppInfoCachingLogic(
            pm = context.packageManager,
            instantAppResolver = this::isInstantApp,
            errorLogger = this::logPersistently,
        )

    init {
        updateSystemState()
    }
@@ -273,8 +281,8 @@ constructor(
            if (addToMemCache) cache[cacheKey] = entry
            // Check the DB first.
            val cacheEntryUpdated =
                if (cursor == null) getEntryFromDBLocked(cacheKey, entry, lookupFlags)
                else updateTitleAndIconLocked(cacheKey, entry, cursor, lookupFlags)
                if (cursor == null) getEntryFromDBLocked(cacheKey, entry, lookupFlags, cachingLogic)
                else updateTitleAndIconLocked(cacheKey, entry, cursor, lookupFlags, cachingLogic)

            val obj: T? by lazy { infoProvider.get() }
            if (!cacheEntryUpdated) {
@@ -409,7 +417,7 @@ constructor(
            var entryUpdated = true

            // Check the DB first.
            if (!getEntryFromDBLocked(cacheKey, entry, lookupFlags)) {
            if (!getEntryFromDBLocked(cacheKey, entry, lookupFlags, appInfoCachingLogic)) {
                try {
                    val appInfo =
                        context
@@ -430,33 +438,18 @@ constructor(

                    // Load the full res icon for the application, but if useLowResIcon is set, then
                    // only keep the low resolution icon instead of the larger full-sized icon
                    val appIcon = iconProvider.getIcon(appInfo)
                    if (packageManager.isDefaultApplicationIcon(appIcon)) {
                        logPersistently(
                            String.format("Default icon returned for %s", appInfo.packageName),
                            null,
                        )
                    }

                    val iconInfo =
                        iconFactory.use { li ->
                            li.createBadgedIconBitmap(
                                appIcon,
                                IconOptions().setUser(user).setInstantApp(isInstantApp(appInfo)),
                            )
                        }

                    entry.title = appInfo.loadLabel(packageManager)
                    entry.contentDescription = getUserBadgedLabel(entry.title, user)
                    val iconInfo = appInfoCachingLogic.loadIcon(context, this, appInfo)
                    entry.bitmap =
                        if (lookupFlags.useLowRes())
                            BitmapInfo.of(BitmapInfo.LOW_RES_ICON, iconInfo.color)
                        else iconInfo

                    loadFallbackTitle(appInfo, entry, appInfoCachingLogic, user)

                    // Add the icon in the DB here, since these do not get written during
                    // package updates.
                    val freshnessId = iconProvider.getStateForApp(appInfo)
                    if (freshnessId != null) {
                    appInfoCachingLogic.getFreshnessIdentifier(appInfo, iconProvider)?.let {
                        freshnessId ->
                        addOrUpdateCacheDbEntry(
                            iconInfo,
                            entry.title,
@@ -483,6 +476,7 @@ constructor(
        cacheKey: ComponentKey,
        entry: CacheEntry,
        lookupFlags: CacheLookupFlag,
        cachingLogic: CachingLogic<*>,
    ): Boolean {
        var c: Cursor? = null
        Trace.beginSection("loadIconIndividually")
@@ -497,7 +491,7 @@ constructor(
                    ),
                )
            if (c.moveToNext()) {
                return updateTitleAndIconLocked(cacheKey, entry, c, lookupFlags)
                return updateTitleAndIconLocked(cacheKey, entry, c, lookupFlags, cachingLogic)
            }
        } catch (e: SQLiteException) {
            Log.d(TAG, "Error reading icon cache", e)
@@ -513,6 +507,7 @@ constructor(
        entry: CacheEntry,
        c: Cursor,
        lookupFlags: CacheLookupFlag,
        logic: CachingLogic<*>,
    ): Boolean {
        // Set the alpha to be 255, so that we never have a wrong color
        entry.bitmap =
@@ -552,7 +547,12 @@ constructor(
                val monoIconData = c.getBlob(INDEX_MONO_ICON)
                if (themeController != null && monoIconData != null) {
                    entry.bitmap.themedBitmap =
                        themeController.decode(monoIconData, entry.bitmap, factory)
                        themeController.decode(
                            data = monoIconData,
                            info = entry.bitmap,
                            factory = factory,
                            sourceHint = SourceHint(cacheKey, logic),
                        )
                }
            }
        }
+4 −1
Original line number Diff line number Diff line
@@ -35,7 +35,10 @@ object CachedObjectCachingLogic : CachingLogic<CachedObject> {
    override fun loadIcon(context: Context, cache: BaseIconCache, info: CachedObject): BitmapInfo {
        val d = info.getFullResIcon(cache) ?: return BitmapInfo.LOW_RES_INFO
        cache.iconFactory.use { li ->
            return li.createBadgedIconBitmap(d, IconOptions().setUser(info.user))
            return li.createBadgedIconBitmap(
                d,
                IconOptions().setUser(info.user).setSourceHint(getSourceHint(info, cache)),
            )
        }
    }

Loading