diff options
Diffstat (limited to 'android/src/main')
3 files changed, 68 insertions, 0 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/AppData.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/AppData.kt new file mode 100644 index 0000000000..5bed89c149 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/AppData.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.applist + +data class AppData(val packageName: String, val iconRes: Int, val name: String) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManager.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManager.kt new file mode 100644 index 0000000000..e266f3d044 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManager.kt @@ -0,0 +1,26 @@ +package net.mullvad.mullvadvpn.applist + +import android.content.pm.PackageManager +import android.graphics.drawable.Drawable +import android.os.Looper +import androidx.annotation.WorkerThread +import androidx.collection.LruCache + +class ApplicationsIconManager(private val packageManager: PackageManager) { + private val iconsCache = LruCache<String, Drawable>(500) + + @WorkerThread + fun getAppIcon(packageName: String): Drawable { + check(!Looper.getMainLooper().isCurrentThread) { "Should not be called from MainThread" } + iconsCache.get(packageName)?.let { + return it + } + return packageManager.getApplicationIcon(packageName).also { + iconsCache.put(packageName, it) + } + } + + fun dispose() { + iconsCache.evictAll() + } +} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProvider.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProvider.kt new file mode 100644 index 0000000000..a097ffd231 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProvider.kt @@ -0,0 +1,39 @@ +package net.mullvad.mullvadvpn.applist + +import android.Manifest +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager + +class ApplicationsProvider( + private val packageManager: PackageManager, + private val thisPackageName: String +) { + private val applicationFilterPredicate: (ApplicationInfo) -> Boolean = { appInfo -> + hasInternetPermission(appInfo.packageName) && + isLaunchable(appInfo.packageName) && + !isSelfApplication(appInfo.packageName) + } + + fun getAppsList(): List<AppData> { + return packageManager.getInstalledApplications(PackageManager.GET_META_DATA) + .asSequence() + .filter(applicationFilterPredicate) + .map { info -> + AppData(info.packageName, info.icon, info.loadLabel(packageManager).toString()) + } + .toList() + } + + private fun hasInternetPermission(packageName: String): Boolean { + return PackageManager.PERMISSION_GRANTED == + packageManager.checkPermission(Manifest.permission.INTERNET, packageName) + } + + private fun isLaunchable(packageName: String): Boolean { + return packageManager.getLaunchIntentForPackage(packageName) != null + } + + private fun isSelfApplication(packageName: String): Boolean { + return packageName == thisPackageName + } +} |
