Merge "Moving IconProvider extensions to a separate subclass instead of routing via APIWrapper" into main
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.launcher3.dagger
|
||||
|
||||
import com.android.launcher3.icons.LauncherIconProvider
|
||||
import com.android.launcher3.icons.LauncherIconProviderImpl
|
||||
import com.android.launcher3.uioverrides.QuickstepWidgetHolder.QuickstepWidgetHolderFactory
|
||||
import com.android.launcher3.uioverrides.SystemApiWrapper
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl
|
||||
@@ -41,6 +43,9 @@ abstract class WindowManagerProxyModule {
|
||||
@Module
|
||||
abstract class ApiWrapperModule {
|
||||
@Binds abstract fun bindApiWrapper(systemApiWrapper: SystemApiWrapper): ApiWrapper
|
||||
|
||||
@Binds
|
||||
abstract fun bindIconProvider(iconProviderImpl: LauncherIconProviderImpl): LauncherIconProvider
|
||||
}
|
||||
|
||||
@Module
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageItemInfo
|
||||
import android.content.res.Resources.NotFoundException
|
||||
import android.graphics.drawable.AdaptiveIconDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.Log
|
||||
import com.android.launcher3.LauncherModel
|
||||
import com.android.launcher3.dagger.ApplicationContext
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton
|
||||
import com.android.launcher3.graphics.ShapeDelegate.Circle
|
||||
import com.android.launcher3.graphics.ThemeManager
|
||||
import com.android.launcher3.icons.cache.CachingLogic
|
||||
import com.android.launcher3.icons.cache.LauncherActivityCachingLogic
|
||||
import com.android.launcher3.util.ComponentKey
|
||||
import com.android.launcher3.util.DaggerSingletonTracker
|
||||
import com.android.launcher3.util.Executors.MODEL_EXECUTOR
|
||||
import com.android.launcher3.util.PluginManagerWrapper
|
||||
import com.android.systemui.plugins.IconProcessorPlugin
|
||||
import com.android.systemui.plugins.PluginLifecycleManager
|
||||
import com.android.systemui.plugins.PluginListener
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
/** Extension of LauncherIconProvider with system APIs and plugin support */
|
||||
private const val TAG = "LauncherIconProviderImpl"
|
||||
|
||||
@LauncherAppSingleton
|
||||
class LauncherIconProviderImpl
|
||||
@Inject
|
||||
constructor(
|
||||
@ApplicationContext ctx: Context,
|
||||
themeManager: ThemeManager,
|
||||
private val modelProvider: Provider<LauncherModel>,
|
||||
private val iconCacheProvider: Provider<IconCache>,
|
||||
pluginManagerWrapper: PluginManagerWrapper,
|
||||
lifecycle: DaggerSingletonTracker,
|
||||
) : LauncherIconProvider(ctx, themeManager), PluginListener<IconProcessorPlugin> {
|
||||
|
||||
init {
|
||||
pluginManagerWrapper.addPluginListener(this, IconProcessorPlugin::class.java)
|
||||
lifecycle.addCloseable { pluginManagerWrapper.removePluginListener(this) }
|
||||
}
|
||||
|
||||
private var processor: IconProcessorPlugin? = null
|
||||
|
||||
override fun getApplicationInfoHash(appInfo: ApplicationInfo): String =
|
||||
(appInfo.sourceDir?.hashCode() ?: 0).toString() + " " + appInfo.longVersionCode
|
||||
|
||||
override fun loadPackageIcon(
|
||||
info: PackageItemInfo,
|
||||
appInfo: ApplicationInfo,
|
||||
density: Int,
|
||||
): Drawable? {
|
||||
fun Drawable.preprocess(resId: Int) =
|
||||
processor?.preprocessDrawable(this, resId, appInfo) ?: this
|
||||
|
||||
try {
|
||||
val resources = mContext.packageManager.getResourcesForApplication(appInfo)
|
||||
// Try to load the package item icon first
|
||||
if (info !== appInfo && info.icon != 0) {
|
||||
try {
|
||||
val icon = resources.getDrawableForDensity(info.icon, density, null)
|
||||
if (icon != null) return icon.preprocess(info.icon)
|
||||
} catch (_: NotFoundException) {}
|
||||
}
|
||||
// Load the fallback app icon
|
||||
if (appInfo.icon != 0) {
|
||||
// Tries to load the round icon res, if the app defines it as an adaptive icon
|
||||
if (mThemeManager.iconShape is Circle) {
|
||||
if (appInfo.roundIconRes != 0 && appInfo.roundIconRes != appInfo.icon) {
|
||||
try {
|
||||
val d =
|
||||
resources.getDrawableForDensity(appInfo.roundIconRes, density, null)
|
||||
if (d is AdaptiveIconDrawable) return d.preprocess(appInfo.roundIconRes)
|
||||
} catch (_: NotFoundException) {}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return resources
|
||||
.getDrawableForDensity(appInfo.icon, density, null)
|
||||
?.preprocess(appInfo.icon)
|
||||
} catch (_: NotFoundException) {}
|
||||
}
|
||||
} catch (_: Exception) {}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onPluginLoaded(
|
||||
plugin: IconProcessorPlugin?,
|
||||
pluginContext: Context?,
|
||||
manager: PluginLifecycleManager<IconProcessorPlugin>?,
|
||||
) {
|
||||
plugin?.setIconChangeNotifier { pkg, userHandle ->
|
||||
modelProvider.get().onAppIconChanged(pkg, userHandle)
|
||||
}
|
||||
processor = plugin
|
||||
Log.d(TAG, "Plugin connected $plugin")
|
||||
MODEL_EXECUTOR.execute {
|
||||
iconCacheProvider.get().clearMemoryCache()
|
||||
modelProvider.get().reloadIfActive()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPluginUnloaded(
|
||||
plugin: IconProcessorPlugin?,
|
||||
manager: PluginLifecycleManager<IconProcessorPlugin>?,
|
||||
) {
|
||||
processor = null
|
||||
Log.d(TAG, "Plugin disconnected")
|
||||
}
|
||||
|
||||
override fun notifyIconLoaded(icon: BitmapInfo, key: ComponentKey, logic: CachingLogic<*>) {
|
||||
if (logic == LauncherActivityCachingLogic)
|
||||
processor?.notifyAppIconLoaded(key.componentName, key.user, icon.flags)
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import android.content.IIntentReceiver
|
||||
import android.content.IIntentSender
|
||||
import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.LauncherActivityInfo
|
||||
import android.content.pm.LauncherApps
|
||||
import android.content.pm.ShortcutInfo
|
||||
@@ -198,11 +197,6 @@ open class SystemApiWrapper @Inject constructor(@ApplicationContext context: Con
|
||||
}
|
||||
}
|
||||
|
||||
override fun getApplicationInfoHash(appInfo: ApplicationInfo): String =
|
||||
(appInfo.sourceDir?.hashCode() ?: 0).toString() + " " + appInfo.longVersionCode
|
||||
|
||||
override fun getRoundIconRes(appInfo: ApplicationInfo) = appInfo.roundIconRes
|
||||
|
||||
override fun isFileDrawable(shortcutInfo: ShortcutInfo) =
|
||||
shortcutInfo.hasIconFile() || shortcutInfo.hasIconUri()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user