From d06cb27f909933acaa6b282a47229f3c50b71d8f Mon Sep 17 00:00:00 2001 From: Suphon Thanakornpakapong Date: Wed, 12 Jan 2022 18:21:44 +0700 Subject: [PATCH] Abstract custom icon pack logic from icon pack class --- .../src/app/lawnchair/icons/CustomIconPack.kt | 138 ++++++++++++++++++ lawnchair/src/app/lawnchair/icons/IconPack.kt | 128 ++-------------- .../app/lawnchair/icons/IconPackProvider.kt | 2 +- 3 files changed, 149 insertions(+), 119 deletions(-) create mode 100644 lawnchair/src/app/lawnchair/icons/CustomIconPack.kt diff --git a/lawnchair/src/app/lawnchair/icons/CustomIconPack.kt b/lawnchair/src/app/lawnchair/icons/CustomIconPack.kt new file mode 100644 index 0000000000..9f37bfa789 --- /dev/null +++ b/lawnchair/src/app/lawnchair/icons/CustomIconPack.kt @@ -0,0 +1,138 @@ +package app.lawnchair.icons + +import android.content.ComponentName +import android.content.Context +import android.content.pm.PackageManager +import android.content.res.Resources +import android.content.res.XmlResourceParser +import android.graphics.drawable.Drawable +import android.util.Xml +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import org.xmlpull.v1.XmlPullParserFactory +import java.io.IOException + +class CustomIconPack(context: Context, packPackageName: String) : + IconPack(context, packPackageName) { + + private val packResources = context.packageManager.getResourcesForApplication(packPackageName) + private val componentMap = mutableMapOf() + private val calendarMap = mutableMapOf() + private val clockMap = mutableMapOf() + private val clockMetas = mutableMapOf() + + private val idCache = mutableMapOf() + + private var _label: String = "" + override val label get() = _label + + override fun getIcon(componentName: ComponentName) = componentMap[componentName] + override fun getCalendar(componentName: ComponentName) = calendarMap[componentName] + override fun getClock(entry: IconEntry) = clockMetas[entry] + + override fun getCalendars(): MutableSet = calendarMap.keys + override fun getClocks(): MutableSet = clockMap.keys + + override fun getIcon(iconEntry: IconEntry, iconDpi: Int): Drawable? { + val id = getDrawableId(iconEntry.name) + if (id == 0) return null + return try { + ExtendedBitmapDrawable.wrap( + packResources, + packResources.getDrawableForDensity(id, iconDpi, null), + true + ) + } catch (e: Resources.NotFoundException) { + null + } + } + + override fun loadInternal() { + val pm = context.packageManager + _label = pm.getApplicationInfo(packPackageName, 0).loadLabel(pm).toString() + val parseXml = getXml("appfilter") ?: return + val compStart = "ComponentInfo{" + val compStartLength = compStart.length + val compEnd = "}" + val compEndLength = compEnd.length + try { + while (parseXml.next() != XmlPullParser.END_DOCUMENT) { + if (parseXml.eventType != XmlPullParser.START_TAG) continue + val name = parseXml.name + val isCalendar = name == "calendar" + when (name) { + "item", "calendar" -> { + var componentName: String? = parseXml["component"] + val drawableName = parseXml[if (isCalendar) "prefix" else "drawable"] + if (componentName != null && drawableName != null) { + if (componentName.startsWith(compStart) && componentName.endsWith(compEnd)) { + componentName = componentName.substring(compStartLength, componentName.length - compEndLength) + } + val parsed = ComponentName.unflattenFromString(componentName) + if (parsed != null) { + if (isCalendar) { + calendarMap[parsed] = CalendarIconEntry(this, drawableName) + } else { + componentMap[parsed] = IconEntry(this, drawableName) + } + } + } + } + "dynamic-clock" -> { + val drawableName = parseXml["drawable"] + if (drawableName != null) { + if (parseXml is XmlResourceParser) { + clockMetas[IconEntry(this, drawableName)] = ClockMetadata( + parseXml.getAttributeIntValue(null, "hourLayerIndex", -1), + parseXml.getAttributeIntValue(null, "minuteLayerIndex", -1), + parseXml.getAttributeIntValue(null, "secondLayerIndex", -1), + parseXml.getAttributeIntValue(null, "defaultHour", 0), + parseXml.getAttributeIntValue(null, "defaultMinute", 0), + parseXml.getAttributeIntValue(null, "defaultSecond", 0)) + } + } + } + } + } + componentMap.forEach { (componentName, iconEntry) -> + if (clockMetas.containsKey(iconEntry)) { + clockMap[componentName] = iconEntry + } + } + } catch (e: PackageManager.NameNotFoundException) { + e.printStackTrace() + } catch (e: XmlPullParserException) { + e.printStackTrace() + } catch (e: IOException) { + e.printStackTrace() + } catch (e: IllegalStateException) { + e.printStackTrace() + } + } + + private fun getDrawableId(name: String) = idCache.getOrPut(name) { + packResources.getIdentifier(name, "drawable", packPackageName) + } + + private fun getXml(name: String): XmlPullParser? { + val res: Resources + try { + res = context.packageManager.getResourcesForApplication(packPackageName) + val resourceId = res.getIdentifier(name, "xml", packPackageName) + return if (0 != resourceId) { + context.packageManager.getXml(packPackageName, resourceId, null) + } else { + val factory = XmlPullParserFactory.newInstance() + val parser = factory.newPullParser() + parser.setInput(res.assets.open("$name.xml"), Xml.Encoding.UTF_8.toString()) + parser + } + } catch (e: PackageManager.NameNotFoundException) { + } catch (e: IOException) { + } catch (e: XmlPullParserException) { + } + return null + } +} + +private operator fun XmlPullParser.get(key: String): String? = this.getAttributeValue(null, key) diff --git a/lawnchair/src/app/lawnchair/icons/IconPack.kt b/lawnchair/src/app/lawnchair/icons/IconPack.kt index ac3ab691da..1bca38a18e 100644 --- a/lawnchair/src/app/lawnchair/icons/IconPack.kt +++ b/lawnchair/src/app/lawnchair/icons/IconPack.kt @@ -14,23 +14,14 @@ import org.xmlpull.v1.XmlPullParserFactory import java.io.IOException import java.util.concurrent.Semaphore -class IconPack( - private val context: Context, +abstract class IconPack( + protected val context: Context, val packPackageName: String, - private val packResources: Resources ) { private var waiter: Semaphore? = Semaphore(0) private val deferredLoad: Deferred - private var _label: String = "" - val label get() = _label - - private val componentMap = mutableMapOf() - private val calendarMap = mutableMapOf() - private val clockMap = mutableMapOf() - private val clockMetas = mutableMapOf() - - private val idCache = mutableMapOf() + abstract val label: String init { deferredLoad = scope.async(Dispatchers.IO) { @@ -51,118 +42,19 @@ class IconPack( } } - fun getIcon(componentName: ComponentName) = componentMap[componentName] - fun getCalendar(componentName: ComponentName) = calendarMap[componentName] - fun getClock(entry: IconEntry) = clockMetas[entry] + abstract fun getIcon(componentName: ComponentName): IconEntry? + abstract fun getCalendar(componentName: ComponentName): CalendarIconEntry? + abstract fun getClock(entry: IconEntry): ClockMetadata? - fun getCalendars(): MutableSet = calendarMap.keys - fun getClocks(): MutableSet = clockMap.keys + abstract fun getCalendars(): MutableSet + abstract fun getClocks(): MutableSet - fun getIcon(iconEntry: IconEntry, iconDpi: Int): Drawable? { - val id = getDrawableId(iconEntry.name) - if (id == 0) return null - return try { - ExtendedBitmapDrawable.wrap( - packResources, - packResources.getDrawableForDensity(id, iconDpi, null), - true - ) - } catch (e: Resources.NotFoundException) { - null - } - } - - private fun getDrawableId(name: String) = idCache.getOrPut(name) { - packResources.getIdentifier(name, "drawable", packPackageName) - } + abstract fun getIcon(iconEntry: IconEntry, iconDpi: Int): Drawable? @Suppress("BlockingMethodInNonBlockingContext") - private fun loadInternal() { - val pm = context.packageManager - _label = pm.getApplicationInfo(packPackageName, 0).loadLabel(pm).toString() - val parseXml = getXml("appfilter") ?: return - val compStart = "ComponentInfo{" - val compStartLength = compStart.length - val compEnd = "}" - val compEndLength = compEnd.length - try { - while (parseXml.next() != XmlPullParser.END_DOCUMENT) { - if (parseXml.eventType != XmlPullParser.START_TAG) continue - val name = parseXml.name - val isCalendar = name == "calendar" - when (name) { - "item", "calendar" -> { - var componentName: String? = parseXml["component"] - val drawableName = parseXml[if (isCalendar) "prefix" else "drawable"] - if (componentName != null && drawableName != null) { - if (componentName.startsWith(compStart) && componentName.endsWith(compEnd)) { - componentName = componentName.substring(compStartLength, componentName.length - compEndLength) - } - val parsed = ComponentName.unflattenFromString(componentName) - if (parsed != null) { - if (isCalendar) { - calendarMap[parsed] = CalendarIconEntry(this, drawableName) - } else { - componentMap[parsed] = IconEntry(this, drawableName) - } - } - } - } - "dynamic-clock" -> { - val drawableName = parseXml["drawable"] - if (drawableName != null) { - if (parseXml is XmlResourceParser) { - clockMetas[IconEntry(this, drawableName)] = ClockMetadata( - parseXml.getAttributeIntValue(null, "hourLayerIndex", -1), - parseXml.getAttributeIntValue(null, "minuteLayerIndex", -1), - parseXml.getAttributeIntValue(null, "secondLayerIndex", -1), - parseXml.getAttributeIntValue(null, "defaultHour", 0), - parseXml.getAttributeIntValue(null, "defaultMinute", 0), - parseXml.getAttributeIntValue(null, "defaultSecond", 0)) - } - } - } - } - } - componentMap.forEach { (componentName, iconEntry) -> - if (clockMetas.containsKey(iconEntry)) { - clockMap[componentName] = iconEntry - } - } - } catch (e: PackageManager.NameNotFoundException) { - e.printStackTrace() - } catch (e: XmlPullParserException) { - e.printStackTrace() - } catch (e: IOException) { - e.printStackTrace() - } catch (e: IllegalStateException) { - e.printStackTrace() - } - } - - private fun getXml(name: String): XmlPullParser? { - val res: Resources - try { - res = context.packageManager.getResourcesForApplication(packPackageName) - val resourceId = res.getIdentifier(name, "xml", packPackageName) - return if (0 != resourceId) { - context.packageManager.getXml(packPackageName, resourceId, null) - } else { - val factory = XmlPullParserFactory.newInstance() - val parser = factory.newPullParser() - parser.setInput(res.assets.open("$name.xml"), Xml.Encoding.UTF_8.toString()) - parser - } - } catch (e: PackageManager.NameNotFoundException) { - } catch (e: IOException) { - } catch (e: XmlPullParserException) { - } - return null - } + protected abstract fun loadInternal() companion object { private val scope = CoroutineScope(Dispatchers.IO) + CoroutineName("IconPack") } } - -private operator fun XmlPullParser.get(key: String): String? = this.getAttributeValue(null, key) diff --git a/lawnchair/src/app/lawnchair/icons/IconPackProvider.kt b/lawnchair/src/app/lawnchair/icons/IconPackProvider.kt index 9093583107..02a07b4547 100644 --- a/lawnchair/src/app/lawnchair/icons/IconPackProvider.kt +++ b/lawnchair/src/app/lawnchair/icons/IconPackProvider.kt @@ -15,7 +15,7 @@ class IconPackProvider(private val context: Context) { return iconPacks.getOrPut(packageName) { try { val packResources = context.packageManager.getResourcesForApplication(packageName) - IconPack(context, packageName, packResources) + CustomIconPack(context, packageName) } catch (e: PackageManager.NameNotFoundException) { null }