From 07152813534424168eb101d75ae6ac1f4bc6d58f Mon Sep 17 00:00:00 2001 From: Marcin Simonides Date: Mon, 20 Sep 2021 15:00:15 +0200 Subject: [PATCH] Load app label and icon via resources [VPNAND-631]. This way it is possible to release resources earlier using Assets.close(). --- .../android/ui/splittunneling/AppsDialog.kt | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/protonvpn/android/ui/splittunneling/AppsDialog.kt b/app/src/main/java/com/protonvpn/android/ui/splittunneling/AppsDialog.kt index 02c051ca8..c6287d23c 100644 --- a/app/src/main/java/com/protonvpn/android/ui/splittunneling/AppsDialog.kt +++ b/app/src/main/java/com/protonvpn/android/ui/splittunneling/AppsDialog.kt @@ -22,10 +22,15 @@ import android.Manifest import android.app.ActivityManager import android.content.pm.ApplicationInfo import android.content.pm.PackageManager +import android.content.res.Resources +import android.graphics.drawable.Drawable +import android.os.Build import android.os.Process +import android.text.TextUtils import android.view.View import android.widget.ProgressBar import android.widget.TextView +import androidx.core.content.res.ResourcesCompat import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -49,6 +54,9 @@ private const val MEMORY_STAT_CODE = "summary.code" private const val GC_TIMEOUT_MS = 1000L private const val GC_CHECK_DELAY_MS = 100L +private const val MAX_SAFE_LABEL_CHARS = 1000 +private const val MAX_SAFE_LABEL_DP = 500f + @ContentLayout(R.layout.dialog_split_tunnel) class AppsDialog : BaseDialog() { private lateinit var adapter: AppsAdapter @@ -134,11 +142,36 @@ class AppsDialog : BaseDialog() { packageManager: PackageManager, appInfo: ApplicationInfo ): SelectedApplicationEntry { - val label = appInfo.loadLabel(packageManager) - val icon = appInfo.loadIcon(packageManager) + val appResources = packageManager.getResourcesForApplication(appInfo) + val label = getLabel(appResources, appInfo.labelRes) ?: appInfo.packageName + val icon = getIcon(appResources, appInfo.icon) ?: packageManager.defaultActivityIcon + appResources.assets.close() return SelectedApplicationEntry(appInfo.packageName, label.toString(), icon) } + private fun getLabel(appResources: Resources, labelResource: Int): String? = + try { + val label = appResources.getString(labelResource) + if (Build.VERSION.SDK_INT >= 29) { + val flags = TextUtils.SAFE_STRING_FLAG_TRIM or TextUtils.SAFE_STRING_FLAG_FIRST_LINE + TextUtils + .makeSafeForPresentation(label, MAX_SAFE_LABEL_CHARS, MAX_SAFE_LABEL_DP, flags) + .toString() + } else { + label + } + } catch (e: Resources.NotFoundException) { + // For some app packages resources fail to load, as if the ID is incorrect. + null + } + + private fun getIcon(appResources: Resources, iconResource: Int): Drawable? = + try { + ResourcesCompat.getDrawable(appResources, iconResource, null) + } catch (e: Resources.NotFoundException) { + null + } + @Suppress("ExplicitGarbageCollectionCall") private suspend fun tryReleaseMemory(initialCodeSizeKb: Int) { // Loading application metadata with loadLabel and loadIcon increases memory use in the