Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9da7ca77 authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

refactor(updates): avoid refetching CleanAPK details per package for signature matching

Reuse the CleanAPK app details already needed during update discovery when checking F-Droid signature matches.

This avoids one getApplicationDetails() call per candidate package, reduces redundant network/repository work, and speeds up update scans for apps installed from other stores without changing matching logic.
parent 675fb6fc
Loading
Loading
Loading
Loading
+42 −7
Original line number Diff line number Diff line
@@ -75,9 +75,11 @@ class UpdatesManagerImpl @Inject constructor(
                    .filterNot { it in fdroidInstalledApps }
                    .toMutableList()

                val cleanApkAppsByPackage = getCleanApkDetailsByPackage(otherStoresInstalledApps)

                // This list is based on app signatures
                val updatableFDroidApps =
                    findPackagesMatchingFDroidSignatures(otherStoresInstalledApps)
                    findPackagesMatchingFDroidSignatures(otherStoresInstalledApps, cleanApkAppsByPackage)
                openSourceInstalledApps.addAll(updatableFDroidApps)

                otherStoresInstalledApps.removeAll(updatableFDroidApps)
@@ -141,9 +143,11 @@ class UpdatesManagerImpl @Inject constructor(
                .filterNot { it in fdroidInstalledApps }
                .toMutableList()

            val cleanApkAppsByPackage = getCleanApkDetailsByPackage(otherStoresInstalledApps)

            // This list is based on app signatures
            val updatableFDroidApps =
                findPackagesMatchingFDroidSignatures(otherStoresInstalledApps)
                findPackagesMatchingFDroidSignatures(otherStoresInstalledApps, cleanApkAppsByPackage)

            openSourceInstalledApps.addAll(updatableFDroidApps)
        }
@@ -304,19 +308,28 @@ class UpdatesManagerImpl @Inject constructor(
     *
     * Map is String : String = package name : signature
     */
    private suspend fun getFDroidAppsAndSignatures(installedPackageNames: List<String>): Map<String, String> {
    private suspend fun getFDroidAppsAndSignatures(
        installedPackageNames: List<String>,
        cleanApkAppsByPackage: Map<String, Application?>,
    ): Map<String, String> {
        val appsAndSignatures = hashMapOf<String, String>()
        for (packageName in installedPackageNames) {
            updateAppsWithPGPSignature(packageName, appsAndSignatures)
            updateAppsWithPGPSignature(packageName, appsAndSignatures, cleanApkAppsByPackage)
        }
        return appsAndSignatures
    }

    private suspend fun updateAppsWithPGPSignature(
        packageName: String,
        appsAndSignatures: HashMap<String, String>
        appsAndSignatures: HashMap<String, String>,
        cleanApkAppsByPackage: Map<String, Application?>,
    ) {
        val apps = applicationRepository.getApplicationDetails(listOf(packageName), Source.OPEN_SOURCE).first
        val cleanApkApplication = cleanApkAppsByPackage[packageName]
        val apps = when {
            cleanApkApplication != null -> listOf(cleanApkApplication)
            cleanApkAppsByPackage.containsKey(packageName) -> emptyList()
            else -> applicationRepository.getApplicationDetails(listOf(packageName), Source.OPEN_SOURCE).first
        }
        if (apps.isEmpty()) {
            return
        }
@@ -357,8 +370,12 @@ class UpdatesManagerImpl @Inject constructor(
     */
    private suspend fun findPackagesMatchingFDroidSignatures(
        installedPackageNames: List<String>,
        cleanApkAppsByPackage: Map<String, Application?>,
    ): List<String> {
        val fDroidAppsAndSignatures = getFDroidAppsAndSignatures(installedPackageNames)
        val fDroidAppsAndSignatures = getFDroidAppsAndSignatures(
            installedPackageNames,
            cleanApkAppsByPackage,
        )

        val fDroidUpdatablePackageNames = fDroidAppsAndSignatures.filter {
            if (it.value.isEmpty()) return@filter false
@@ -373,6 +390,24 @@ class UpdatesManagerImpl @Inject constructor(
        return fDroidUpdatablePackageNames
    }

    private suspend fun getCleanApkDetailsByPackage(
        packageNames: List<String>,
    ): Map<String, Application?> {
        if (packageNames.isEmpty()) {
            return emptyMap()
        }

        val appsResult = applicationRepository.getApplicationDetails(packageNames, Source.OPEN_SOURCE)
        if (appsResult.second != ResultStatus.OK) {
            return emptyMap()
        }

        val appsByPackage = appsResult.first
            .filter { it.package_name.isNotBlank() }
            .associateBy { it.package_name }
        return packageNames.associateWith { appsByPackage[it] }
    }

    /**
     * Get signature version for the installed version of the app.
     * A signature version is like "update_XX" where XX is a 2-digit number.