diff --git a/app/src/androidTest/java/com/leanbitlab/lwidget/GetBestIntentBenchmarkTest.kt b/app/src/androidTest/java/com/leanbitlab/lwidget/GetBestIntentBenchmarkTest.kt new file mode 100644 index 0000000..8017d9e --- /dev/null +++ b/app/src/androidTest/java/com/leanbitlab/lwidget/GetBestIntentBenchmarkTest.kt @@ -0,0 +1,74 @@ +package com.leanbitlab.lwidget + +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Test +import org.junit.runner.RunWith +import kotlin.system.measureNanoTime + +@RunWith(AndroidJUnit4::class) +class GetBestIntentBenchmarkTest { + + @Test + fun benchmarkGetBestIntent() { + val context = ApplicationProvider.getApplicationContext() + val clockPackages = listOf("com.android.deskclock", "com.google.android.deskclock", "com.simplemobiletools.clock", "org.fossify.clock", "com.sec.android.app.clockpackage", "com.coloros.alarmclock", "com.miui.calculator") + val fallback = Intent(android.provider.AlarmClock.ACTION_SHOW_ALARMS) + + // Warmup + for (i in 0 until 10) { + getBestIntent(context, clockPackages, fallback) + } + + val iterations = 100 + val timeNormal = measureNanoTime { + for (i in 0 until iterations) { + getBestIntent(context, clockPackages, fallback) + } + } + + // Warmup Cached + for (i in 0 until 10) { + getBestIntentCached(context, clockPackages, fallback) + } + + val timeCached = measureNanoTime { + for (i in 0 until iterations) { + getBestIntentCached(context, clockPackages, fallback) + } + } + + println("BENCHMARK_NORMAL: ${timeNormal / iterations} ns per call") + println("BENCHMARK_CACHED: ${timeCached / iterations} ns per call") + } + + private fun getBestIntent(context: Context, packages: List, fallback: Intent): Intent { + val pm = context.packageManager + for (pkg in packages) { + val intent = pm.getLaunchIntentForPackage(pkg) + if (intent != null) { + return intent + } + } + return fallback + } + + private var cachedClockIntent: Intent? = null + + private fun getBestIntentCached(context: Context, packages: List, fallback: Intent): Intent { + if (cachedClockIntent != null) return cachedClockIntent!! + val pm = context.packageManager + for (pkg in packages) { + val intent = pm.getLaunchIntentForPackage(pkg) + if (intent != null) { + cachedClockIntent = intent + return intent + } + } + cachedClockIntent = fallback + return fallback + } +} diff --git a/app/src/main/java/com/leanbitlab/lwidget/AwidgetProvider.kt b/app/src/main/java/com/leanbitlab/lwidget/AwidgetProvider.kt index 50d5cc4..9e21b57 100644 --- a/app/src/main/java/com/leanbitlab/lwidget/AwidgetProvider.kt +++ b/app/src/main/java/com/leanbitlab/lwidget/AwidgetProvider.kt @@ -1353,14 +1353,27 @@ class AwidgetProvider : AppWidgetProvider() { } } + private data class CacheEntry(val intent: Intent, val timestamp: Long) + private val intentCache = java.util.concurrent.ConcurrentHashMap() + private const val CACHE_TTL_MS = 60000L // 60 seconds TTL + private fun getBestIntent(context: Context, packages: List, fallback: Intent): Intent { + val cacheKey = packages.joinToString(",") + "|" + fallback.action + val cached = intentCache[cacheKey] + val now = android.os.SystemClock.elapsedRealtime() + if (cached != null && (now - cached.timestamp < CACHE_TTL_MS)) { + return Intent(cached.intent) // Return a copy to prevent mutation + } + val pm = context.packageManager for (pkg in packages) { val intent = pm.getLaunchIntentForPackage(pkg) if (intent != null) { + intentCache[cacheKey] = CacheEntry(Intent(intent), now) return intent } } + intentCache[cacheKey] = CacheEntry(Intent(fallback), now) return fallback } }